novelWriter 2.4.3__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.3.dist-info → novelWriter-2.5b1.dist-info}/METADATA +4 -5
  2. {novelWriter-2.4.3.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 +98 -126
  82. novelwriter/gui/dochighlight.py +237 -183
  83. novelwriter/gui/docviewer.py +46 -94
  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 +23 -48
  95. novelwriter/guimain.py +50 -71
  96. novelwriter/shared.py +30 -15
  97. novelwriter/tools/dictionaries.py +8 -12
  98. novelwriter/tools/lipsum.py +2 -4
  99. novelwriter/tools/manusbuild.py +1 -3
  100. novelwriter/tools/manuscript.py +66 -145
  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.3.dist-info → novelWriter-2.5b1.dist-info}/LICENSE.md +0 -0
  107. {novelWriter-2.4.3.dist-info → novelWriter-2.5b1.dist-info}/WHEEL +0 -0
  108. {novelWriter-2.4.3.dist-info → novelWriter-2.5b1.dist-info}/entry_points.txt +0 -0
  109. {novelWriter-2.4.3.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,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,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,8 +321,11 @@ class GuiDocEditor(QPlainTextEdit):
328
321
  # Reload spell check and dictionaries
329
322
  SHARED.updateSpellCheckLanguage()
330
323
 
331
- # Set font
332
- self.initFont()
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()
333
329
 
334
330
  # Update highlighter settings
335
331
  self._qDocument.syntaxHighlighter.initHighlighter()
@@ -379,23 +375,6 @@ class GuiDocEditor(QPlainTextEdit):
379
375
 
380
376
  return
381
377
 
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
378
  def loadText(self, tHandle: str, tLine: int | None = None) -> bool:
400
379
  """Load text from a document into the editor. If we have an I/O
401
380
  error, we must handle this and clear the editor so that we don't
@@ -492,7 +471,6 @@ class GuiDocEditor(QPlainTextEdit):
492
471
  cC, wC, pC = standardCounter(docText)
493
472
  self._updateDocCounts(cC, wC, pC)
494
473
 
495
- self.saveCursorPosition()
496
474
  if not self._nwDocument.writeDocument(docText):
497
475
  saveOk = False
498
476
  if self._nwDocument.hashError:
@@ -855,14 +833,15 @@ class GuiDocEditor(QPlainTextEdit):
855
833
  )
856
834
  return
857
835
 
858
- def insertText(self, insert: str | nwDocInsert) -> bool:
836
+ def insertText(self, insert: str | nwDocInsert) -> None:
859
837
  """Insert a specific type of text at the cursor position."""
860
838
  if self._docHandle is None:
861
839
  logger.error("No document open")
862
- return False
840
+ return
863
841
 
864
- newBlock = False
865
- goAfter = False
842
+ text = ""
843
+ block = False
844
+ after = False
866
845
 
867
846
  if isinstance(insert, str):
868
847
  text = insert
@@ -877,43 +856,41 @@ class GuiDocEditor(QPlainTextEdit):
877
856
  text = self._typDQuoteC
878
857
  elif insert == nwDocInsert.SYNOPSIS:
879
858
  text = "%Synopsis: "
880
- newBlock = True
881
- goAfter = True
859
+ block = True
860
+ after = True
882
861
  elif insert == nwDocInsert.SHORT:
883
862
  text = "%Short: "
884
- newBlock = True
885
- goAfter = True
863
+ block = True
864
+ after = True
886
865
  elif insert == nwDocInsert.NEW_PAGE:
887
866
  text = "[newpage]"
888
- newBlock = True
889
- goAfter = False
867
+ block = True
868
+ after = False
890
869
  elif insert == nwDocInsert.VSPACE_S:
891
870
  text = "[vspace]"
892
- newBlock = True
893
- goAfter = False
871
+ block = True
872
+ after = False
894
873
  elif insert == nwDocInsert.VSPACE_M:
895
874
  text = "[vspace:2]"
896
- newBlock = True
897
- goAfter = False
875
+ block = True
876
+ after = False
898
877
  elif insert == nwDocInsert.LIPSUM:
899
878
  text = GuiLipsum.getLipsum(self)
900
- newBlock = True
901
- goAfter = False
902
- else:
903
- return False
904
- else:
905
- return False
879
+ block = True
880
+ after = False
881
+ elif insert == nwDocInsert.FOOTNOTE:
882
+ self._insertCommentStructure(nwComment.FOOTNOTE)
906
883
 
907
884
  if text:
908
- if newBlock:
909
- self.insertNewBlock(text, defaultAfter=goAfter)
885
+ if block:
886
+ self.insertNewBlock(text, defaultAfter=after)
910
887
  else:
911
888
  cursor = self.textCursor()
912
889
  cursor.beginEditBlock()
913
890
  cursor.insertText(text)
914
891
  cursor.endEditBlock()
915
892
 
916
- return True
893
+ return
917
894
 
918
895
  def insertNewBlock(self, text: str, defaultAfter: bool = True) -> bool:
919
896
  """Insert a piece of text on a blank line."""
@@ -1179,7 +1156,8 @@ class GuiDocEditor(QPlainTextEdit):
1179
1156
  lambda _, option=option: self._correctWord(sCursor, option)
1180
1157
  )
1181
1158
  else:
1182
- 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}")
1183
1161
 
1184
1162
  ctxMenu.addSeparator()
1185
1163
  action = ctxMenu.addAction(self.tr("Add Word to Dictionary"))
@@ -1335,9 +1313,8 @@ class GuiDocEditor(QPlainTextEdit):
1335
1313
  self.docSearch.setResultCount(0, 0)
1336
1314
  self._lastFind = None
1337
1315
  if CONFIG.searchNextFile and not goBack:
1338
- self.mainGui.openNextDocument(
1339
- self._docHandle, wrapAround=CONFIG.searchLoop
1340
- )
1316
+ self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
1317
+ QApplication.processEvents()
1341
1318
  self.beginSearch()
1342
1319
  self.setFocus()
1343
1320
  return
@@ -1356,9 +1333,8 @@ class GuiDocEditor(QPlainTextEdit):
1356
1333
 
1357
1334
  if resIdx > maxIdx and self._docHandle:
1358
1335
  if CONFIG.searchNextFile and not goBack:
1359
- self.mainGui.openNextDocument(
1360
- self._docHandle, wrapAround=CONFIG.searchLoop
1361
- )
1336
+ self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
1337
+ QApplication.processEvents()
1362
1338
  self.beginSearch()
1363
1339
  self.setFocus()
1364
1340
  return
@@ -1865,6 +1841,32 @@ class GuiDocEditor(QPlainTextEdit):
1865
1841
 
1866
1842
  return
1867
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
+
1868
1870
  ##
1869
1871
  # Internal Functions
1870
1872
  ##
@@ -2128,8 +2130,6 @@ class GuiDocEditor(QPlainTextEdit):
2128
2130
  self._doReplace = False
2129
2131
  return
2130
2132
 
2131
- # END Class GuiDocEditor
2132
-
2133
2133
 
2134
2134
  class MetaCompleter(QMenu):
2135
2135
  """GuiWidget: Meta Completer Menu
@@ -2207,15 +2207,13 @@ class MetaCompleter(QMenu):
2207
2207
  self.complete.emit(pos, length, value)
2208
2208
  return
2209
2209
 
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
2210
 
2218
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
+ """
2219
2217
 
2220
2218
  def __init__(self, docEditor: GuiDocEditor, forSelection: bool = False) -> None:
2221
2219
  super().__init__()
@@ -2248,8 +2246,6 @@ class BackgroundWordCounter(QRunnable):
2248
2246
 
2249
2247
  return
2250
2248
 
2251
- # END Class BackgroundWordCounter
2252
-
2253
2249
 
2254
2250
  class BackgroundWordCounterSignals(QObject):
2255
2251
  """The QRunnable cannot emit a signal, so we need a simple QObject
@@ -2257,15 +2253,13 @@ class BackgroundWordCounterSignals(QObject):
2257
2253
  """
2258
2254
  countsReady = pyqtSignal(int, int, int)
2259
2255
 
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
2256
 
2268
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
+ """
2269
2263
 
2270
2264
  requestDocAction = pyqtSignal(nwDocAction)
2271
2265
 
@@ -2390,15 +2384,13 @@ class GuiDocToolBar(QWidget):
2390
2384
 
2391
2385
  return
2392
2386
 
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
2387
 
2401
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
+ """
2402
2394
 
2403
2395
  def __init__(self, docEditor: GuiDocEditor) -> None:
2404
2396
  super().__init__(parent=docEditor)
@@ -2546,32 +2538,18 @@ class GuiDocEditSearch(QFrame):
2546
2538
  # Getters
2547
2539
  ##
2548
2540
 
2549
- def getSearchObject(self) -> str | QRegularExpression | QRegExp:
2541
+ def getSearchObject(self) -> str | QRegularExpression:
2550
2542
  """Return the current search text either as text or as a regular
2551
2543
  expression object.
2552
2544
  """
2553
2545
  text = self.searchBox.text()
2554
2546
  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
-
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
2575
2553
  return text
2576
2554
 
2577
2555
  ##
@@ -2775,15 +2753,13 @@ class GuiDocEditSearch(QFrame):
2775
2753
  self.searchBox.setPalette(qPalette)
2776
2754
  return
2777
2755
 
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
2756
 
2786
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
+ """
2787
2763
 
2788
2764
  closeDocumentRequest = pyqtSignal()
2789
2765
  toggleToolBarRequest = pyqtSignal()
@@ -3001,15 +2977,13 @@ class GuiDocEditHeader(QWidget):
3001
2977
  self.docEditor.requestProjectItemSelected.emit(self._docHandle or "", True)
3002
2978
  return
3003
2979
 
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
2980
 
3012
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
+ """
3013
2987
 
3014
2988
  def __init__(self, parent: QWidget) -> None:
3015
2989
  super().__init__(parent=parent)
@@ -3164,7 +3138,7 @@ class GuiDocEditFooter(QWidget):
3164
3138
  sText = ""
3165
3139
  else:
3166
3140
  iPx = round(0.9*SHARED.theme.baseIconHeight)
3167
- status, icon = self._tItem.getImportStatus(incIcon=True)
3141
+ status, icon = self._tItem.getImportStatus()
3168
3142
  sIcon = icon.pixmap(iPx, iPx)
3169
3143
  sText = f"{status} / {self._tItem.describeMe()}"
3170
3144
 
@@ -3195,5 +3169,3 @@ class GuiDocEditFooter(QWidget):
3195
3169
  wText = self._trWordCount.format("0", "+0")
3196
3170
  self.wordsText.setText(wText)
3197
3171
  return
3198
-
3199
- # END Class GuiDocEditFooter