novelWriter 2.4.2__py3-none-any.whl → 2.5b1__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 (109) hide show
  1. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/METADATA +4 -5
  2. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/RECORD +109 -101
  3. novelwriter/__init__.py +33 -39
  4. novelwriter/assets/i18n/project_en_GB.json +1 -0
  5. novelwriter/assets/icons/typicons_dark/icons.conf +2 -0
  6. novelwriter/assets/icons/typicons_dark/nw_font.svg +4 -0
  7. novelwriter/assets/icons/typicons_dark/nw_quote.svg +4 -0
  8. novelwriter/assets/icons/typicons_light/icons.conf +2 -0
  9. novelwriter/assets/icons/typicons_light/nw_font.svg +4 -0
  10. novelwriter/assets/icons/typicons_light/nw_quote.svg +4 -0
  11. novelwriter/assets/manual.pdf +0 -0
  12. novelwriter/assets/sample.zip +0 -0
  13. novelwriter/assets/syntax/cyberpunk_night.conf +5 -3
  14. novelwriter/assets/syntax/default_dark.conf +32 -18
  15. novelwriter/assets/syntax/default_light.conf +24 -10
  16. novelwriter/assets/syntax/dracula.conf +44 -0
  17. novelwriter/assets/syntax/grey_dark.conf +5 -4
  18. novelwriter/assets/syntax/grey_light.conf +5 -4
  19. novelwriter/assets/syntax/light_owl.conf +7 -6
  20. novelwriter/assets/syntax/night_owl.conf +7 -6
  21. novelwriter/assets/syntax/snazzy.conf +42 -0
  22. novelwriter/assets/syntax/solarized_dark.conf +4 -3
  23. novelwriter/assets/syntax/solarized_light.conf +4 -3
  24. novelwriter/assets/syntax/tango.conf +27 -11
  25. novelwriter/assets/syntax/tomorrow.conf +6 -5
  26. novelwriter/assets/syntax/tomorrow_night.conf +7 -6
  27. novelwriter/assets/syntax/tomorrow_night_blue.conf +6 -5
  28. novelwriter/assets/syntax/tomorrow_night_bright.conf +6 -5
  29. novelwriter/assets/syntax/tomorrow_night_eighties.conf +6 -5
  30. novelwriter/assets/text/credits_en.htm +4 -1
  31. novelwriter/assets/themes/cyberpunk_night.conf +2 -0
  32. novelwriter/assets/themes/default_dark.conf +1 -0
  33. novelwriter/assets/themes/default_light.conf +1 -0
  34. novelwriter/assets/themes/dracula.conf +47 -0
  35. novelwriter/assets/themes/solarized_dark.conf +1 -0
  36. novelwriter/assets/themes/solarized_light.conf +1 -0
  37. novelwriter/common.py +31 -9
  38. novelwriter/config.py +118 -84
  39. novelwriter/constants.py +40 -26
  40. novelwriter/core/buildsettings.py +63 -66
  41. novelwriter/core/coretools.py +2 -22
  42. novelwriter/core/docbuild.py +51 -40
  43. novelwriter/core/document.py +3 -5
  44. novelwriter/core/index.py +115 -45
  45. novelwriter/core/item.py +8 -19
  46. novelwriter/core/options.py +2 -4
  47. novelwriter/core/project.py +23 -57
  48. novelwriter/core/projectdata.py +1 -3
  49. novelwriter/core/projectxml.py +12 -15
  50. novelwriter/core/sessions.py +3 -5
  51. novelwriter/core/spellcheck.py +4 -9
  52. novelwriter/core/status.py +211 -164
  53. novelwriter/core/storage.py +0 -8
  54. novelwriter/core/tohtml.py +94 -100
  55. novelwriter/core/tokenizer.py +199 -112
  56. novelwriter/core/{tomd.py → tomarkdown.py} +97 -78
  57. novelwriter/core/toodt.py +212 -148
  58. novelwriter/core/toqdoc.py +403 -0
  59. novelwriter/core/tree.py +5 -7
  60. novelwriter/dialogs/about.py +3 -5
  61. novelwriter/dialogs/docmerge.py +1 -3
  62. novelwriter/dialogs/docsplit.py +1 -3
  63. novelwriter/dialogs/editlabel.py +0 -2
  64. novelwriter/dialogs/preferences.py +111 -88
  65. novelwriter/dialogs/projectsettings.py +216 -180
  66. novelwriter/dialogs/quotes.py +3 -4
  67. novelwriter/dialogs/wordlist.py +3 -9
  68. novelwriter/enum.py +31 -25
  69. novelwriter/error.py +8 -15
  70. novelwriter/extensions/circularprogress.py +5 -6
  71. novelwriter/extensions/configlayout.py +18 -18
  72. novelwriter/extensions/eventfilters.py +1 -5
  73. novelwriter/extensions/modified.py +50 -13
  74. novelwriter/extensions/novelselector.py +1 -3
  75. novelwriter/extensions/pagedsidebar.py +9 -12
  76. novelwriter/extensions/simpleprogress.py +1 -3
  77. novelwriter/extensions/statusled.py +1 -3
  78. novelwriter/extensions/switch.py +4 -6
  79. novelwriter/extensions/switchbox.py +7 -6
  80. novelwriter/extensions/versioninfo.py +3 -9
  81. novelwriter/gui/doceditor.py +132 -133
  82. novelwriter/gui/dochighlight.py +237 -183
  83. novelwriter/gui/docviewer.py +61 -97
  84. novelwriter/gui/docviewerpanel.py +3 -10
  85. novelwriter/gui/editordocument.py +1 -3
  86. novelwriter/gui/itemdetails.py +7 -11
  87. novelwriter/gui/mainmenu.py +11 -7
  88. novelwriter/gui/noveltree.py +11 -24
  89. novelwriter/gui/outline.py +11 -23
  90. novelwriter/gui/projtree.py +26 -43
  91. novelwriter/gui/search.py +1 -3
  92. novelwriter/gui/sidebar.py +2 -6
  93. novelwriter/gui/statusbar.py +6 -10
  94. novelwriter/gui/theme.py +26 -51
  95. novelwriter/guimain.py +50 -71
  96. novelwriter/shared.py +30 -15
  97. novelwriter/tools/dictionaries.py +12 -15
  98. novelwriter/tools/lipsum.py +2 -4
  99. novelwriter/tools/manusbuild.py +1 -3
  100. novelwriter/tools/manuscript.py +71 -144
  101. novelwriter/tools/manussettings.py +67 -73
  102. novelwriter/tools/noveldetails.py +6 -11
  103. novelwriter/tools/welcome.py +2 -16
  104. novelwriter/tools/writingstats.py +6 -9
  105. novelwriter/types.py +45 -3
  106. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/LICENSE.md +0 -0
  107. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/WHEEL +0 -0
  108. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/entry_points.txt +0 -0
  109. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/top_level.txt +0 -0
@@ -26,16 +26,16 @@ from __future__ import annotations
26
26
  import json
27
27
  import logging
28
28
 
29
- from time import sleep
30
29
  from datetime import datetime
30
+ from time import sleep
31
31
  from urllib.error import HTTPError
32
32
  from urllib.request import Request, urlopen
33
33
 
34
- from PyQt5.QtGui import QDesktopServices
35
34
  from PyQt5.QtCore import QObject, QRunnable, QUrl, pyqtSignal, pyqtSlot
35
+ from PyQt5.QtGui import QDesktopServices
36
36
  from PyQt5.QtWidgets import QLabel, QVBoxLayout, QWidget
37
37
 
38
- from novelwriter import CONFIG, SHARED, __version__, __date__, __domain__
38
+ from novelwriter import CONFIG, SHARED, __date__, __domain__, __version__
39
39
  from novelwriter.common import formatVersion
40
40
  from novelwriter.constants import nwConst
41
41
 
@@ -111,8 +111,6 @@ class VersionInfoWidget(QWidget):
111
111
  self._lblRelease.setText(self._trLatest.format(reason or self.tr("Failed")))
112
112
  return
113
113
 
114
- # END Class VersionInfoWidget
115
-
116
114
 
117
115
  class _Retriever(QRunnable):
118
116
 
@@ -144,10 +142,6 @@ class _Retriever(QRunnable):
144
142
  self.signals.dataReady.emit("", str(e))
145
143
  return
146
144
 
147
- # END Class _Retriever
148
-
149
145
 
150
146
  class _RetrieverSignal(QObject):
151
147
  dataReady = pyqtSignal(str, str)
152
-
153
- # END Class _RetrieverSignal
@@ -36,15 +36,14 @@ 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
- QColor, QCursor, QFont, QKeyEvent, QKeySequence, QMouseEvent, QPalette,
47
- QPixmap, QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption
45
+ QColor, QCursor, QKeyEvent, QKeySequence, QMouseEvent, QPalette, QPixmap,
46
+ QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption
48
47
  )
49
48
  from PyQt5.QtWidgets import (
50
49
  QAction, QApplication, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit,
@@ -55,7 +54,7 @@ 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
59
58
  from novelwriter.extensions.eventfilters import WheelEventFilter
60
59
  from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton
61
60
  from novelwriter.gui.dochighlight import BLOCK_META, BLOCK_TITLE
@@ -69,9 +68,6 @@ from novelwriter.types import (
69
68
  QtMoveAnchor, QtMoveLeft, QtMoveRight
70
69
  )
71
70
 
72
- if TYPE_CHECKING: # pragma: no cover
73
- from novelwriter.guimain import GuiMain
74
-
75
71
  logger = logging.getLogger(__name__)
76
72
 
77
73
 
@@ -82,8 +78,6 @@ class _SelectAction(Enum):
82
78
  KEEP_POSITION = 2
83
79
  MOVE_AFTER = 3
84
80
 
85
- # END Class _SelectAction
86
-
87
81
 
88
82
  class GuiDocEditor(QPlainTextEdit):
89
83
  """Gui Widget: Main Document Editor"""
@@ -107,15 +101,14 @@ class GuiDocEditor(QPlainTextEdit):
107
101
  requestProjectItemSelected = pyqtSignal(str, bool)
108
102
  requestProjectItemRenamed = pyqtSignal(str, str)
109
103
  requestNewNoteCreation = pyqtSignal(str, nwItemClass)
104
+ requestNextDocument = pyqtSignal(str, bool)
110
105
 
111
- def __init__(self, mainGui: GuiMain) -> None:
112
- super().__init__(parent=mainGui)
106
+ def __init__(self, parent: QWidget) -> None:
107
+ super().__init__(parent=parent)
113
108
 
114
109
  logger.debug("Create: GuiDocEditor")
115
110
 
116
111
  # Class Variables
117
- self.mainGui = mainGui
118
-
119
112
  self._nwDocument = None
120
113
  self._nwItem = None
121
114
 
@@ -328,11 +321,11 @@ class GuiDocEditor(QPlainTextEdit):
328
321
  # Reload spell check and dictionaries
329
322
  SHARED.updateSpellCheckLanguage()
330
323
 
331
- # Set font
332
- font = QFont()
333
- font.setFamily(CONFIG.textFont)
334
- font.setPointSize(CONFIG.textSize)
335
- self._qDocument.setDefaultFont(font)
324
+ # Set the font. See issues #1862 and #1875.
325
+ self.setFont(CONFIG.textFont)
326
+ self.docHeader.updateFont()
327
+ self.docFooter.updateFont()
328
+ self.docSearch.updateFont()
336
329
 
337
330
  # Update highlighter settings
338
331
  self._qDocument.syntaxHighlighter.initHighlighter()
@@ -478,7 +471,6 @@ class GuiDocEditor(QPlainTextEdit):
478
471
  cC, wC, pC = standardCounter(docText)
479
472
  self._updateDocCounts(cC, wC, pC)
480
473
 
481
- self.saveCursorPosition()
482
474
  if not self._nwDocument.writeDocument(docText):
483
475
  saveOk = False
484
476
  if self._nwDocument.hashError:
@@ -841,14 +833,15 @@ class GuiDocEditor(QPlainTextEdit):
841
833
  )
842
834
  return
843
835
 
844
- def insertText(self, insert: str | nwDocInsert) -> bool:
836
+ def insertText(self, insert: str | nwDocInsert) -> None:
845
837
  """Insert a specific type of text at the cursor position."""
846
838
  if self._docHandle is None:
847
839
  logger.error("No document open")
848
- return False
840
+ return
849
841
 
850
- newBlock = False
851
- goAfter = False
842
+ text = ""
843
+ block = False
844
+ after = False
852
845
 
853
846
  if isinstance(insert, str):
854
847
  text = insert
@@ -863,43 +856,41 @@ class GuiDocEditor(QPlainTextEdit):
863
856
  text = self._typDQuoteC
864
857
  elif insert == nwDocInsert.SYNOPSIS:
865
858
  text = "%Synopsis: "
866
- newBlock = True
867
- goAfter = True
859
+ block = True
860
+ after = True
868
861
  elif insert == nwDocInsert.SHORT:
869
862
  text = "%Short: "
870
- newBlock = True
871
- goAfter = True
863
+ block = True
864
+ after = True
872
865
  elif insert == nwDocInsert.NEW_PAGE:
873
866
  text = "[newpage]"
874
- newBlock = True
875
- goAfter = False
867
+ block = True
868
+ after = False
876
869
  elif insert == nwDocInsert.VSPACE_S:
877
870
  text = "[vspace]"
878
- newBlock = True
879
- goAfter = False
871
+ block = True
872
+ after = False
880
873
  elif insert == nwDocInsert.VSPACE_M:
881
874
  text = "[vspace:2]"
882
- newBlock = True
883
- goAfter = False
875
+ block = True
876
+ after = False
884
877
  elif insert == nwDocInsert.LIPSUM:
885
878
  text = GuiLipsum.getLipsum(self)
886
- newBlock = True
887
- goAfter = False
888
- else:
889
- return False
890
- else:
891
- return False
879
+ block = True
880
+ after = False
881
+ elif insert == nwDocInsert.FOOTNOTE:
882
+ self._insertCommentStructure(nwComment.FOOTNOTE)
892
883
 
893
884
  if text:
894
- if newBlock:
895
- self.insertNewBlock(text, defaultAfter=goAfter)
885
+ if block:
886
+ self.insertNewBlock(text, defaultAfter=after)
896
887
  else:
897
888
  cursor = self.textCursor()
898
889
  cursor.beginEditBlock()
899
890
  cursor.insertText(text)
900
891
  cursor.endEditBlock()
901
892
 
902
- return True
893
+ return
903
894
 
904
895
  def insertNewBlock(self, text: str, defaultAfter: bool = True) -> bool:
905
896
  """Insert a piece of text on a blank line."""
@@ -1165,7 +1156,8 @@ class GuiDocEditor(QPlainTextEdit):
1165
1156
  lambda _, option=option: self._correctWord(sCursor, option)
1166
1157
  )
1167
1158
  else:
1168
- ctxMenu.addAction("%s %s" % (nwUnicode.U_ENDASH, self.tr("No Suggestions")))
1159
+ trNone = self.tr("No Suggestions")
1160
+ ctxMenu.addAction(f"{nwUnicode.U_ENDASH} {trNone}")
1169
1161
 
1170
1162
  ctxMenu.addSeparator()
1171
1163
  action = ctxMenu.addAction(self.tr("Add Word to Dictionary"))
@@ -1321,9 +1313,8 @@ class GuiDocEditor(QPlainTextEdit):
1321
1313
  self.docSearch.setResultCount(0, 0)
1322
1314
  self._lastFind = None
1323
1315
  if CONFIG.searchNextFile and not goBack:
1324
- self.mainGui.openNextDocument(
1325
- self._docHandle, wrapAround=CONFIG.searchLoop
1326
- )
1316
+ self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
1317
+ QApplication.processEvents()
1327
1318
  self.beginSearch()
1328
1319
  self.setFocus()
1329
1320
  return
@@ -1342,9 +1333,8 @@ class GuiDocEditor(QPlainTextEdit):
1342
1333
 
1343
1334
  if resIdx > maxIdx and self._docHandle:
1344
1335
  if CONFIG.searchNextFile and not goBack:
1345
- self.mainGui.openNextDocument(
1346
- self._docHandle, wrapAround=CONFIG.searchLoop
1347
- )
1336
+ self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
1337
+ QApplication.processEvents()
1348
1338
  self.beginSearch()
1349
1339
  self.setFocus()
1350
1340
  return
@@ -1851,6 +1841,32 @@ class GuiDocEditor(QPlainTextEdit):
1851
1841
 
1852
1842
  return
1853
1843
 
1844
+ def _insertCommentStructure(self, style: nwComment) -> None:
1845
+ """Insert a shortcut/comment combo."""
1846
+ if self._docHandle and style == nwComment.FOOTNOTE:
1847
+ self.saveText() # Index must be up to date
1848
+ key = SHARED.project.index.newCommentKey(self._docHandle, style)
1849
+ code = nwShortcode.COMMENT_STYLES[nwComment.FOOTNOTE]
1850
+
1851
+ cursor = self.textCursor()
1852
+ block = cursor.block()
1853
+ text = block.text().rstrip()
1854
+ if not text or text.startswith("@"):
1855
+ logger.error("Invalid footnote location")
1856
+ return
1857
+
1858
+ cursor.beginEditBlock()
1859
+ cursor.insertText(code.format(key))
1860
+ cursor.setPosition(block.position() + block.length() - 1)
1861
+ cursor.insertBlock()
1862
+ cursor.insertBlock()
1863
+ cursor.insertText(f"%Footnote.{key}: ")
1864
+ cursor.endEditBlock()
1865
+
1866
+ self.setTextCursor(cursor)
1867
+
1868
+ return
1869
+
1854
1870
  ##
1855
1871
  # Internal Functions
1856
1872
  ##
@@ -2114,8 +2130,6 @@ class GuiDocEditor(QPlainTextEdit):
2114
2130
  self._doReplace = False
2115
2131
  return
2116
2132
 
2117
- # END Class GuiDocEditor
2118
-
2119
2133
 
2120
2134
  class MetaCompleter(QMenu):
2121
2135
  """GuiWidget: Meta Completer Menu
@@ -2193,15 +2207,13 @@ class MetaCompleter(QMenu):
2193
2207
  self.complete.emit(pos, length, value)
2194
2208
  return
2195
2209
 
2196
- # END Class MetaCompleter
2197
-
2198
-
2199
- # =============================================================================================== #
2200
- # The Off-GUI Thread Word Counter
2201
- # A runnable for the word counter to be run in the thread pool off the main GUI thread.
2202
- # =============================================================================================== #
2203
2210
 
2204
2211
  class BackgroundWordCounter(QRunnable):
2212
+ """The Off-GUI Thread Word Counter
2213
+
2214
+ A runnable for the word counter to be run in the thread pool off the
2215
+ main GUI thread.
2216
+ """
2205
2217
 
2206
2218
  def __init__(self, docEditor: GuiDocEditor, forSelection: bool = False) -> None:
2207
2219
  super().__init__()
@@ -2234,8 +2246,6 @@ class BackgroundWordCounter(QRunnable):
2234
2246
 
2235
2247
  return
2236
2248
 
2237
- # END Class BackgroundWordCounter
2238
-
2239
2249
 
2240
2250
  class BackgroundWordCounterSignals(QObject):
2241
2251
  """The QRunnable cannot emit a signal, so we need a simple QObject
@@ -2243,15 +2253,13 @@ class BackgroundWordCounterSignals(QObject):
2243
2253
  """
2244
2254
  countsReady = pyqtSignal(int, int, int)
2245
2255
 
2246
- # END Class BackgroundWordCounterSignals
2247
-
2248
-
2249
- # =============================================================================================== #
2250
- # The Formatting and Options Fold Out Menu
2251
- # Only used by DocEditor, and is opened by the first button in the header
2252
- # =============================================================================================== #
2253
2256
 
2254
2257
  class GuiDocToolBar(QWidget):
2258
+ """The Formatting and Options Fold Out Menu
2259
+
2260
+ Only used by DocEditor, and is opened by the first button in the
2261
+ header.
2262
+ """
2255
2263
 
2256
2264
  requestDocAction = pyqtSignal(nwDocAction)
2257
2265
 
@@ -2376,15 +2384,13 @@ class GuiDocToolBar(QWidget):
2376
2384
 
2377
2385
  return
2378
2386
 
2379
- # END Class GuiDocToolBar
2380
-
2381
-
2382
- # =============================================================================================== #
2383
- # The Embedded Document Search/Replace Feature
2384
- # Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
2385
- # =============================================================================================== #
2386
2387
 
2387
2388
  class GuiDocEditSearch(QFrame):
2389
+ """The Embedded Document Search/Replace Feature
2390
+
2391
+ Only used by DocEditor, and is at a fixed position in the
2392
+ QTextEdit's viewport.
2393
+ """
2388
2394
 
2389
2395
  def __init__(self, docEditor: GuiDocEditor) -> None:
2390
2396
  super().__init__(parent=docEditor)
@@ -2396,9 +2402,6 @@ class GuiDocEditSearch(QFrame):
2396
2402
  iSz = SHARED.theme.baseIconSize
2397
2403
  mPx = CONFIG.pxInt(6)
2398
2404
 
2399
- self.boxFont = SHARED.theme.guiFont
2400
- self.boxFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
2401
-
2402
2405
  self.setContentsMargins(0, 0, 0, 0)
2403
2406
  self.setAutoFillBackground(True)
2404
2407
  self.setFrameStyle(QFrame.Shape.StyledPanel | QFrame.Shadow.Plain)
@@ -2410,12 +2413,10 @@ class GuiDocEditSearch(QFrame):
2410
2413
  # ==========
2411
2414
 
2412
2415
  self.searchBox = QLineEdit(self)
2413
- self.searchBox.setFont(self.boxFont)
2414
2416
  self.searchBox.setPlaceholderText(self.tr("Search for"))
2415
2417
  self.searchBox.returnPressed.connect(self._doSearch)
2416
2418
 
2417
2419
  self.replaceBox = QLineEdit(self)
2418
- self.replaceBox.setFont(self.boxFont)
2419
2420
  self.replaceBox.setPlaceholderText(self.tr("Replace with"))
2420
2421
  self.replaceBox.returnPressed.connect(self._doReplace)
2421
2422
 
@@ -2425,12 +2426,9 @@ class GuiDocEditSearch(QFrame):
2425
2426
  self.searchOpt.setContentsMargins(0, 0, 0, 0)
2426
2427
 
2427
2428
  self.searchLabel = QLabel(self.tr("Search"), self)
2428
- self.searchLabel.setFont(self.boxFont)
2429
2429
  self.searchLabel.setIndent(CONFIG.pxInt(6))
2430
2430
 
2431
2431
  self.resultLabel = QLabel("?/?", self)
2432
- self.resultLabel.setFont(self.boxFont)
2433
- self.resultLabel.setMinimumWidth(SHARED.theme.getTextWidth("?/?", self.boxFont))
2434
2432
 
2435
2433
  self.toggleCase = QAction(self.tr("Case Sensitive"), self)
2436
2434
  self.toggleCase.setCheckable(True)
@@ -2515,6 +2513,7 @@ class GuiDocEditSearch(QFrame):
2515
2513
  self.replaceButton.setVisible(False)
2516
2514
  self.adjustSize()
2517
2515
 
2516
+ self.updateFont()
2518
2517
  self.updateTheme()
2519
2518
 
2520
2519
  logger.debug("Ready: GuiDocEditSearch")
@@ -2539,32 +2538,18 @@ class GuiDocEditSearch(QFrame):
2539
2538
  # Getters
2540
2539
  ##
2541
2540
 
2542
- def getSearchObject(self) -> str | QRegularExpression | QRegExp:
2541
+ def getSearchObject(self) -> str | QRegularExpression:
2543
2542
  """Return the current search text either as text or as a regular
2544
2543
  expression object.
2545
2544
  """
2546
2545
  text = self.searchBox.text()
2547
2546
  if CONFIG.searchRegEx:
2548
- # Using the Unicode-capable QRegularExpression class was
2549
- # only added in Qt 5.13. Otherwise, 5.3 and up supports
2550
- # only the QRegExp class.
2551
- if CONFIG.verQtValue >= 0x050d00:
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
2558
- else: # pragma: no cover
2559
- # >= 50300 to < 51300
2560
- if CONFIG.searchCase:
2561
- rxOpt = Qt.CaseSensitivity.CaseSensitive
2562
- else:
2563
- rxOpt = Qt.CaseSensitivity.CaseInsensitive
2564
- regEx = QRegExp(text, rxOpt)
2565
- self._alertSearchValid(regEx.isValid())
2566
- return regEx
2567
-
2547
+ rxOpt = QRegularExpression.PatternOption.UseUnicodePropertiesOption
2548
+ if not CONFIG.searchCase:
2549
+ rxOpt |= QRegularExpression.PatternOption.CaseInsensitiveOption
2550
+ regEx = QRegularExpression(text, rxOpt)
2551
+ self._alertSearchValid(regEx.isValid())
2552
+ return regEx
2568
2553
  return text
2569
2554
 
2570
2555
  ##
@@ -2598,7 +2583,9 @@ class GuiDocEditSearch(QFrame):
2598
2583
  numCount = f"{lim:n}+" if (resCount or 0) > lim else f"{resCount:n}"
2599
2584
  sCurrRes = "?" if currRes is None else str(currRes)
2600
2585
  sResCount = "?" if resCount is None else numCount
2601
- minWidth = SHARED.theme.getTextWidth(f"{sResCount}//{sResCount}", self.boxFont)
2586
+ minWidth = SHARED.theme.getTextWidth(
2587
+ f"{sResCount}//{sResCount}", SHARED.theme.guiFontSmall
2588
+ )
2602
2589
  self.resultLabel.setText(f"{sCurrRes}/{sResCount}")
2603
2590
  self.resultLabel.setMinimumWidth(minWidth)
2604
2591
  self.adjustSize()
@@ -2609,6 +2596,18 @@ class GuiDocEditSearch(QFrame):
2609
2596
  # Methods
2610
2597
  ##
2611
2598
 
2599
+ def updateFont(self) -> None:
2600
+ """Update the font settings."""
2601
+ self.setFont(SHARED.theme.guiFont)
2602
+ self.searchBox.setFont(SHARED.theme.guiFontSmall)
2603
+ self.replaceBox.setFont(SHARED.theme.guiFontSmall)
2604
+ self.searchLabel.setFont(SHARED.theme.guiFontSmall)
2605
+ self.resultLabel.setFont(SHARED.theme.guiFontSmall)
2606
+ self.resultLabel.setMinimumWidth(
2607
+ SHARED.theme.getTextWidth("?/?", SHARED.theme.guiFontSmall)
2608
+ )
2609
+ return
2610
+
2612
2611
  def updateTheme(self) -> None:
2613
2612
  """Update theme elements."""
2614
2613
  qPalette = QApplication.palette()
@@ -2754,15 +2753,13 @@ class GuiDocEditSearch(QFrame):
2754
2753
  self.searchBox.setPalette(qPalette)
2755
2754
  return
2756
2755
 
2757
- # END Class GuiDocEditSearch
2758
-
2759
-
2760
- # =============================================================================================== #
2761
- # The Embedded Document Header
2762
- # Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
2763
- # =============================================================================================== #
2764
2756
 
2765
2757
  class GuiDocEditHeader(QWidget):
2758
+ """The Embedded Document Header
2759
+
2760
+ Only used by DocEditor, and is at a fixed position in the
2761
+ QTextEdit's viewport.
2762
+ """
2766
2763
 
2767
2764
  closeDocumentRequest = pyqtSignal()
2768
2765
  toggleToolBarRequest = pyqtSignal()
@@ -2793,10 +2790,6 @@ class GuiDocEditHeader(QWidget):
2793
2790
  self.itemTitle.setAlignment(QtAlignCenterTop)
2794
2791
  self.itemTitle.setFixedHeight(iPx)
2795
2792
 
2796
- lblFont = self.itemTitle.font()
2797
- lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
2798
- self.itemTitle.setFont(lblFont)
2799
-
2800
2793
  # Other Widgets
2801
2794
  self.outlineMenu = QMenu(self)
2802
2795
 
@@ -2850,6 +2843,7 @@ class GuiDocEditHeader(QWidget):
2850
2843
  self.setContentsMargins(0, 0, 0, 0)
2851
2844
  self.setMinimumHeight(iPx + 2*mPx)
2852
2845
 
2846
+ self.updateFont()
2853
2847
  self.updateTheme()
2854
2848
 
2855
2849
  logger.debug("Ready: GuiDocEditHeader")
@@ -2888,6 +2882,12 @@ class GuiDocEditHeader(QWidget):
2888
2882
  logger.debug("Document outline updated in %.3f ms", 1000*(time() - tStart))
2889
2883
  return
2890
2884
 
2885
+ def updateFont(self) -> None:
2886
+ """Update the font settings."""
2887
+ self.setFont(SHARED.theme.guiFont)
2888
+ self.itemTitle.setFont(SHARED.theme.guiFontSmall)
2889
+ return
2890
+
2891
2891
  def updateTheme(self) -> None:
2892
2892
  """Update theme elements."""
2893
2893
  self.tbButton.setThemeIcon("menu")
@@ -2977,15 +2977,13 @@ class GuiDocEditHeader(QWidget):
2977
2977
  self.docEditor.requestProjectItemSelected.emit(self._docHandle or "", True)
2978
2978
  return
2979
2979
 
2980
- # END Class GuiDocEditHeader
2981
-
2982
-
2983
- # =============================================================================================== #
2984
- # The Embedded Document Footer
2985
- # Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
2986
- # =============================================================================================== #
2987
2980
 
2988
2981
  class GuiDocEditFooter(QWidget):
2982
+ """The Embedded Document Footer
2983
+
2984
+ Only used by DocEditor, and is at a fixed position in the
2985
+ QTextEdit's viewport.
2986
+ """
2989
2987
 
2990
2988
  def __init__(self, parent: QWidget) -> None:
2991
2989
  super().__init__(parent=parent)
@@ -3001,9 +2999,6 @@ class GuiDocEditFooter(QWidget):
3001
2999
  bSp = CONFIG.pxInt(4)
3002
3000
  hSp = CONFIG.pxInt(6)
3003
3001
 
3004
- lblFont = self.font()
3005
- lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
3006
-
3007
3002
  # Cached Translations
3008
3003
  self._trLineCount = self.tr("Line: {0} ({1})")
3009
3004
  self._trWordCount = self.tr("Words: {0} ({1})")
@@ -3026,7 +3021,6 @@ class GuiDocEditFooter(QWidget):
3026
3021
  self.statusText.setAutoFillBackground(True)
3027
3022
  self.statusText.setFixedHeight(fPx)
3028
3023
  self.statusText.setAlignment(QtAlignLeftTop)
3029
- self.statusText.setFont(lblFont)
3030
3024
 
3031
3025
  # Lines
3032
3026
  self.linesIcon = QLabel("", self)
@@ -3041,7 +3035,6 @@ class GuiDocEditFooter(QWidget):
3041
3035
  self.linesText.setAutoFillBackground(True)
3042
3036
  self.linesText.setFixedHeight(fPx)
3043
3037
  self.linesText.setAlignment(QtAlignLeftTop)
3044
- self.linesText.setFont(lblFont)
3045
3038
 
3046
3039
  # Words
3047
3040
  self.wordsIcon = QLabel("", self)
@@ -3056,7 +3049,6 @@ class GuiDocEditFooter(QWidget):
3056
3049
  self.wordsText.setAutoFillBackground(True)
3057
3050
  self.wordsText.setFixedHeight(fPx)
3058
3051
  self.wordsText.setAlignment(QtAlignLeftTop)
3059
- self.wordsText.setFont(lblFont)
3060
3052
 
3061
3053
  # Assemble Layout
3062
3054
  self.outerBox = QHBoxLayout()
@@ -3079,6 +3071,7 @@ class GuiDocEditFooter(QWidget):
3079
3071
  self.setMinimumHeight(fPx + 2*mPx)
3080
3072
 
3081
3073
  # Fix the Colours
3074
+ self.updateFont()
3082
3075
  self.updateTheme()
3083
3076
 
3084
3077
  # Initialise Info
@@ -3092,6 +3085,14 @@ class GuiDocEditFooter(QWidget):
3092
3085
  # Methods
3093
3086
  ##
3094
3087
 
3088
+ def updateFont(self) -> None:
3089
+ """Update the font settings."""
3090
+ self.setFont(SHARED.theme.guiFont)
3091
+ self.statusText.setFont(SHARED.theme.guiFontSmall)
3092
+ self.linesText.setFont(SHARED.theme.guiFontSmall)
3093
+ self.wordsText.setFont(SHARED.theme.guiFontSmall)
3094
+ return
3095
+
3095
3096
  def updateTheme(self) -> None:
3096
3097
  """Update theme elements."""
3097
3098
  iPx = round(0.9*SHARED.theme.baseIconHeight)
@@ -3137,7 +3138,7 @@ class GuiDocEditFooter(QWidget):
3137
3138
  sText = ""
3138
3139
  else:
3139
3140
  iPx = round(0.9*SHARED.theme.baseIconHeight)
3140
- status, icon = self._tItem.getImportStatus(incIcon=True)
3141
+ status, icon = self._tItem.getImportStatus()
3141
3142
  sIcon = icon.pixmap(iPx, iPx)
3142
3143
  sText = f"{status} / {self._tItem.describeMe()}"
3143
3144
 
@@ -3168,5 +3169,3 @@ class GuiDocEditFooter(QWidget):
3168
3169
  wText = self._trWordCount.format("0", "+0")
3169
3170
  self.wordsText.setText(wText)
3170
3171
  return
3171
-
3172
- # END Class GuiDocEditFooter