novelWriter 2.4b1__py3-none-any.whl → 2.4rc1__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 (72) hide show
  1. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/METADATA +5 -6
  2. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/RECORD +62 -66
  3. novelwriter/__init__.py +5 -5
  4. novelwriter/assets/icons/none.svg +4 -0
  5. novelwriter/assets/icons/typicons_dark/icons.conf +2 -2
  6. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
  7. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
  8. novelwriter/assets/icons/typicons_light/icons.conf +2 -2
  9. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
  10. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
  11. novelwriter/assets/manual.pdf +0 -0
  12. novelwriter/assets/sample.zip +0 -0
  13. novelwriter/common.py +6 -1
  14. novelwriter/config.py +8 -4
  15. novelwriter/core/coretools.py +21 -22
  16. novelwriter/core/status.py +3 -2
  17. novelwriter/core/toodt.py +332 -355
  18. novelwriter/dialogs/about.py +9 -11
  19. novelwriter/dialogs/docmerge.py +17 -14
  20. novelwriter/dialogs/docsplit.py +14 -12
  21. novelwriter/dialogs/editlabel.py +5 -4
  22. novelwriter/dialogs/preferences.py +28 -33
  23. novelwriter/dialogs/projectsettings.py +29 -26
  24. novelwriter/dialogs/quotes.py +10 -9
  25. novelwriter/dialogs/wordlist.py +15 -12
  26. novelwriter/error.py +13 -11
  27. novelwriter/extensions/circularprogress.py +12 -8
  28. novelwriter/extensions/configlayout.py +1 -3
  29. novelwriter/extensions/modified.py +33 -2
  30. novelwriter/extensions/pagedsidebar.py +16 -14
  31. novelwriter/extensions/simpleprogress.py +3 -1
  32. novelwriter/extensions/statusled.py +3 -1
  33. novelwriter/extensions/switch.py +10 -9
  34. novelwriter/extensions/switchbox.py +14 -13
  35. novelwriter/gui/doceditor.py +182 -225
  36. novelwriter/gui/dochighlight.py +4 -4
  37. novelwriter/gui/docviewer.py +53 -57
  38. novelwriter/gui/docviewerpanel.py +16 -13
  39. novelwriter/gui/editordocument.py +4 -4
  40. novelwriter/gui/itemdetails.py +45 -48
  41. novelwriter/gui/noveltree.py +22 -20
  42. novelwriter/gui/outline.py +87 -88
  43. novelwriter/gui/projtree.py +31 -29
  44. novelwriter/gui/search.py +75 -29
  45. novelwriter/gui/sidebar.py +24 -28
  46. novelwriter/gui/statusbar.py +14 -14
  47. novelwriter/gui/theme.py +47 -35
  48. novelwriter/guimain.py +35 -31
  49. novelwriter/shared.py +5 -5
  50. novelwriter/tools/dictionaries.py +13 -12
  51. novelwriter/tools/lipsum.py +20 -17
  52. novelwriter/tools/manusbuild.py +35 -27
  53. novelwriter/tools/manuscript.py +68 -73
  54. novelwriter/tools/manussettings.py +68 -73
  55. novelwriter/tools/noveldetails.py +20 -18
  56. novelwriter/tools/welcome.py +47 -43
  57. novelwriter/tools/writingstats.py +61 -55
  58. novelwriter/types.py +90 -0
  59. novelwriter/assets/icons/typicons_dark/typ_arrow-down.svg +0 -4
  60. novelwriter/assets/icons/typicons_dark/typ_arrow-right.svg +0 -4
  61. novelwriter/assets/icons/typicons_light/typ_arrow-down.svg +0 -4
  62. novelwriter/assets/icons/typicons_light/typ_arrow-right.svg +0 -4
  63. novelwriter/core/__init__.py +0 -3
  64. novelwriter/dialogs/__init__.py +0 -3
  65. novelwriter/extensions/__init__.py +0 -3
  66. novelwriter/gui/__init__.py +0 -3
  67. novelwriter/text/__init__.py +0 -3
  68. novelwriter/tools/__init__.py +0 -3
  69. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/LICENSE.md +0 -0
  70. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/WHEEL +0 -0
  71. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/entry_points.txt +0 -0
  72. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/top_level.txt +0 -0
@@ -40,16 +40,15 @@ from typing import TYPE_CHECKING
40
40
 
41
41
  from PyQt5.QtCore import (
42
42
  pyqtSignal, pyqtSlot, QObject, QPoint, QRegExp, QRegularExpression,
43
- QRunnable, QSize, Qt, QTimer
43
+ QRunnable, Qt, QTimer
44
44
  )
45
45
  from PyQt5.QtGui import (
46
46
  QColor, QCursor, QFont, QKeyEvent, QKeySequence, QMouseEvent, QPalette,
47
47
  QPixmap, QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption
48
48
  )
49
49
  from PyQt5.QtWidgets import (
50
- QAction, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu,
51
- QPlainTextEdit, QPushButton, QShortcut, QToolBar, QToolButton, QVBoxLayout,
52
- QWidget, qApp
50
+ QAction, QApplication, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit,
51
+ QMenu, QPlainTextEdit, QShortcut, QToolBar, QVBoxLayout, QWidget
53
52
  )
54
53
 
55
54
  from novelwriter import CONFIG, SHARED
@@ -58,12 +57,17 @@ from novelwriter.constants import nwConst, nwKeyWords, nwShortcode, nwUnicode
58
57
  from novelwriter.core.document import NWDocument
59
58
  from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemClass, nwTrinary
60
59
  from novelwriter.extensions.eventfilters import WheelEventFilter
61
- from novelwriter.extensions.modified import NIconToolButton
60
+ from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton
62
61
  from novelwriter.gui.dochighlight import BLOCK_META, BLOCK_TITLE
63
62
  from novelwriter.gui.editordocument import GuiTextDocument
64
63
  from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
65
64
  from novelwriter.text.counting import standardCounter
66
65
  from novelwriter.tools.lipsum import GuiLipsum
66
+ from novelwriter.types import (
67
+ QtAlignCenterTop, QtAlignJustify, QtAlignLeft, QtAlignLeftTop,
68
+ QtAlignRight, QtKeepAnchor, QtModCtrl, QtMouseLeft, QtModeNone, QtModShift,
69
+ QtMoveAnchor, QtMoveLeft, QtMoveRight
70
+ )
67
71
 
68
72
  if TYPE_CHECKING: # pragma: no cover
69
73
  from novelwriter.guimain import GuiMain
@@ -92,6 +96,7 @@ class GuiDocEditor(QPlainTextEdit):
92
96
  # Custom Signals
93
97
  statusMessage = pyqtSignal(str)
94
98
  docCountsChanged = pyqtSignal(str, int, int, int)
99
+ docTextChanged = pyqtSignal(str, float)
95
100
  editedStatusChanged = pyqtSignal(bool)
96
101
  loadDocumentTagRequest = pyqtSignal(str, Enum)
97
102
  novelStructureChanged = pyqtSignal()
@@ -178,12 +183,12 @@ class GuiDocEditor(QPlainTextEdit):
178
183
  self.keyContext.activated.connect(self._openContextFromCursor)
179
184
 
180
185
  self.followTag1 = QShortcut(self)
181
- self.followTag1.setKey(Qt.Key.Key_Return | Qt.KeyboardModifier.ControlModifier)
186
+ self.followTag1.setKey(Qt.Key.Key_Return | QtModCtrl)
182
187
  self.followTag1.setContext(Qt.ShortcutContext.WidgetShortcut)
183
188
  self.followTag1.activated.connect(self._processTag)
184
189
 
185
190
  self.followTag2 = QShortcut(self)
186
- self.followTag2.setKey(Qt.Key.Key_Enter | Qt.KeyboardModifier.ControlModifier)
191
+ self.followTag2.setKey(Qt.Key.Key_Enter | QtModCtrl)
187
192
  self.followTag2.setContext(Qt.ShortcutContext.WidgetShortcut)
188
193
  self.followTag2.activated.connect(self._processTag)
189
194
 
@@ -209,6 +214,10 @@ class GuiDocEditor(QPlainTextEdit):
209
214
  self.wheelEventFilter = WheelEventFilter(self)
210
215
  self.installEventFilter(self.wheelEventFilter)
211
216
 
217
+ # Function Mapping
218
+ self.closeSearch = self.docSearch.closeSearch
219
+ self.searchVisible = self.docSearch.isVisible
220
+
212
221
  # Finalise
213
222
  self.updateSyntaxColours()
214
223
  self.initEditor()
@@ -338,7 +347,7 @@ class GuiDocEditor(QPlainTextEdit):
338
347
  options = QTextOption()
339
348
 
340
349
  if CONFIG.doJustify:
341
- options.setAlignment(Qt.AlignmentFlag.AlignJustify)
350
+ options.setAlignment(QtAlignJustify)
342
351
  if CONFIG.showTabsNSpaces:
343
352
  options.setFlags(options.flags() | QTextOption.Flag.ShowTabsAndSpaces)
344
353
  if CONFIG.showLineEndings:
@@ -390,13 +399,13 @@ class GuiDocEditor(QPlainTextEdit):
390
399
  self.clearEditor()
391
400
  return False
392
401
 
393
- qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
402
+ QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
394
403
  self._docHandle = tHandle
395
404
 
396
405
  self._allowAutoReplace(False)
397
406
  self._qDocument.setTextContent(docText, tHandle)
398
407
  self._allowAutoReplace(True)
399
- qApp.processEvents()
408
+ QApplication.processEvents()
400
409
 
401
410
  self._lastEdit = time()
402
411
  self._lastActive = time()
@@ -420,12 +429,12 @@ class GuiDocEditor(QPlainTextEdit):
420
429
  self.setPlainText("")
421
430
  self.setCursorPosition(0)
422
431
 
423
- qApp.processEvents()
432
+ QApplication.processEvents()
424
433
  self.setDocumentChanged(False)
425
434
  self._qDocument.clearUndoRedoStacks()
426
435
  self.docToolBar.setVisible(CONFIG.showEditToolBar)
427
436
 
428
- qApp.restoreOverrideCursor()
437
+ QApplication.restoreOverrideCursor()
429
438
 
430
439
  # Update the status bar
431
440
  if self._nwItem is not None:
@@ -442,11 +451,11 @@ class GuiDocEditor(QPlainTextEdit):
442
451
  """Replace the text of the current document with the provided
443
452
  text. This also clears undo history.
444
453
  """
445
- qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
454
+ QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
446
455
  self.setPlainText(text)
447
456
  self.updateDocMargins()
448
457
  self.setDocumentChanged(True)
449
- qApp.restoreOverrideCursor()
458
+ QApplication.restoreOverrideCursor()
450
459
  return
451
460
 
452
461
  def saveText(self) -> bool:
@@ -533,7 +542,7 @@ class GuiDocEditor(QPlainTextEdit):
533
542
  while self.cursorRect().bottom() > vH and count < 100000:
534
543
  vBar.setValue(vBar.value() + 1)
535
544
  count += 1
536
- qApp.processEvents()
545
+ QApplication.processEvents()
537
546
  return
538
547
 
539
548
  def updateDocMargins(self) -> None:
@@ -593,6 +602,15 @@ class GuiDocEditor(QPlainTextEdit):
593
602
  text = text.replace(nwUnicode.U_PSEP, "\n") # Paragraph separators
594
603
  return text
595
604
 
605
+ def getSelectedText(self) -> str:
606
+ """Get currently selected text."""
607
+ if (cursor := self.textCursor()).hasSelection():
608
+ text = cursor.selectedText()
609
+ text = text.replace(nwUnicode.U_LSEP, "\n") # Line separators
610
+ text = text.replace(nwUnicode.U_PSEP, "\n") # Paragraph separators
611
+ return text
612
+ return ""
613
+
596
614
  def getCursorPosition(self) -> int:
597
615
  """Find the cursor position in the document. If the editor has a
598
616
  selection, return the position of the end of the selection.
@@ -639,12 +657,13 @@ class GuiDocEditor(QPlainTextEdit):
639
657
  logger.debug("Cursor moved to line %d", line)
640
658
  return
641
659
 
642
- def setCursorSelection(self, selStart: int, selLength: int) -> None:
660
+ def setCursorSelection(self, start: int, length: int) -> None:
643
661
  """Make a text selection."""
644
- cursor = self.textCursor()
645
- cursor.setPosition(selStart, QTextCursor.MoveMode.MoveAnchor)
646
- cursor.setPosition(selStart + selLength, QTextCursor.MoveMode.KeepAnchor)
647
- self.setTextCursor(cursor)
662
+ if start >= 0 and length > 0:
663
+ cursor = self.textCursor()
664
+ cursor.setPosition(start, QtMoveAnchor)
665
+ cursor.setPosition(start + length, QtKeepAnchor)
666
+ self.setTextCursor(cursor)
648
667
  return
649
668
 
650
669
  ##
@@ -686,9 +705,9 @@ class GuiDocEditor(QPlainTextEdit):
686
705
  """
687
706
  logger.debug("Running spell checker")
688
707
  start = time()
689
- qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
708
+ QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
690
709
  self._qDocument.syntaxHighlighter.rehighlight()
691
- qApp.restoreOverrideCursor()
710
+ QApplication.restoreOverrideCursor()
692
711
  logger.debug("Document highlighted in %.3f ms", 1000*(time() - start))
693
712
  self.statusMessage.emit(self.tr("Spell check complete"))
694
713
  return
@@ -801,7 +820,7 @@ class GuiDocEditor(QPlainTextEdit):
801
820
 
802
821
  def anyFocus(self) -> bool:
803
822
  """Check if any widget or child widget has focus."""
804
- return self.hasFocus() or self.isAncestorOf(qApp.focusWidget())
823
+ return self.hasFocus() or self.isAncestorOf(QApplication.focusWidget())
805
824
 
806
825
  def revealLocation(self) -> None:
807
826
  """Tell the user where on the file system the file in the editor
@@ -910,11 +929,6 @@ class GuiDocEditor(QPlainTextEdit):
910
929
 
911
930
  return True
912
931
 
913
- def closeSearch(self) -> bool:
914
- """Close the search box."""
915
- self.docSearch.closeSearch()
916
- return self.docSearch.isVisible()
917
-
918
932
  ##
919
933
  # Document Events and Maintenance
920
934
  ##
@@ -949,7 +963,7 @@ class GuiDocEditor(QPlainTextEdit):
949
963
  super().keyPressEvent(event)
950
964
  nPos = self.cursorRect().topLeft().y()
951
965
  kMod = event.modifiers()
952
- okMod = kMod in (Qt.KeyboardModifier.NoModifier, Qt.KeyboardModifier.ShiftModifier)
966
+ okMod = kMod in (QtModeNone, QtModShift)
953
967
  okKey = event.key() not in self.MOVE_KEYS
954
968
  if nPos != cPos and okMod and okKey:
955
969
  mPos = CONFIG.autoScrollPos*0.01 * self.viewport().height()
@@ -970,7 +984,7 @@ class GuiDocEditor(QPlainTextEdit):
970
984
  if self.hasFocus():
971
985
  return False
972
986
  elif self.docSearch.isVisible():
973
- return self.docSearch.cycleFocus(next)
987
+ return self.docSearch.cycleFocus()
974
988
  return True
975
989
 
976
990
  def mouseReleaseEvent(self, event: QMouseEvent) -> None:
@@ -978,7 +992,7 @@ class GuiDocEditor(QPlainTextEdit):
978
992
  pressed, check if we're clicking on a tag, and trigger the
979
993
  follow tag function.
980
994
  """
981
- if qApp.keyboardModifiers() == Qt.KeyboardModifier.ControlModifier:
995
+ if QApplication.keyboardModifiers() == QtModCtrl:
982
996
  self._processTag(self.cursorForPosition(event.pos()))
983
997
  super().mouseReleaseEvent(event)
984
998
  return
@@ -1021,8 +1035,8 @@ class GuiDocEditor(QPlainTextEdit):
1021
1035
  @pyqtSlot()
1022
1036
  def toggleSearch(self) -> None:
1023
1037
  """Toggle the visibility of the search box."""
1024
- if self.docSearch.isVisible():
1025
- self.docSearch.closeSearch()
1038
+ if self.searchVisible():
1039
+ self.closeSearch()
1026
1040
  else:
1027
1041
  self.beginSearch()
1028
1042
  return
@@ -1078,8 +1092,8 @@ class GuiDocEditor(QPlainTextEdit):
1078
1092
  block = cursor.block()
1079
1093
  if block.isValid():
1080
1094
  pos += block.position()
1081
- cursor.setPosition(pos, QTextCursor.MoveMode.MoveAnchor)
1082
- cursor.setPosition(pos + length, QTextCursor.MoveMode.KeepAnchor)
1095
+ cursor.setPosition(pos, QtMoveAnchor)
1096
+ cursor.setPosition(pos + length, QtKeepAnchor)
1083
1097
  cursor.insertText(text)
1084
1098
  self._completer.hide()
1085
1099
  return
@@ -1139,9 +1153,7 @@ class GuiDocEditor(QPlainTextEdit):
1139
1153
  block = pCursor.block()
1140
1154
  sCursor = self.textCursor()
1141
1155
  sCursor.setPosition(block.position() + cPos)
1142
- sCursor.movePosition(
1143
- QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor, cLen
1144
- )
1156
+ sCursor.movePosition(QtMoveRight, QtKeepAnchor, cLen)
1145
1157
  if suggest:
1146
1158
  ctxMenu.addSeparator()
1147
1159
  ctxMenu.addAction(self.tr("Spelling Suggestion(s)"))
@@ -1158,7 +1170,7 @@ class GuiDocEditor(QPlainTextEdit):
1158
1170
  action.triggered.connect(lambda: self._addWord(word, block))
1159
1171
 
1160
1172
  # Execute the context menu
1161
- ctxMenu.exec_(self.viewport().mapToGlobal(pos))
1173
+ ctxMenu.exec(self.viewport().mapToGlobal(pos))
1162
1174
  ctxMenu.deleteLater()
1163
1175
 
1164
1176
  return
@@ -1193,18 +1205,19 @@ class GuiDocEditor(QPlainTextEdit):
1193
1205
  if self._docHandle is None:
1194
1206
  return
1195
1207
 
1196
- if self.wCounterDoc.isRunning():
1197
- logger.debug("Word counter is busy")
1198
- return
1199
-
1200
1208
  if time() - self._lastEdit < 25.0:
1201
- logger.debug("Running word counter")
1202
- SHARED.runInThreadPool(self.wCounterDoc)
1209
+ logger.debug("Running document tasks")
1210
+ if not self.wCounterDoc.isRunning():
1211
+ SHARED.runInThreadPool(self.wCounterDoc)
1212
+
1203
1213
  self.docHeader.setOutline({
1204
1214
  block.blockNumber(): block.text()
1205
1215
  for block in self._qDocument.iterBlockByType(BLOCK_TITLE, maxCount=30)
1206
1216
  })
1207
1217
 
1218
+ if self._docChanged:
1219
+ self.docTextChanged.emit(self._docHandle, self._lastEdit)
1220
+
1208
1221
  return
1209
1222
 
1210
1223
  @pyqtSlot(int, int, int)
@@ -1276,11 +1289,7 @@ class GuiDocEditor(QPlainTextEdit):
1276
1289
 
1277
1290
  def beginSearch(self) -> None:
1278
1291
  """Set the selected text as the search text."""
1279
- cursor = self.textCursor()
1280
- if cursor.hasSelection():
1281
- self.docSearch.setSearchText(cursor.selectedText())
1282
- else:
1283
- self.docSearch.setSearchText(None)
1292
+ self.docSearch.setSearchText(self.getSelectedText() or None)
1284
1293
  resS, _ = self.findAllOccurences()
1285
1294
  self.docSearch.setResultCount(None, len(resS))
1286
1295
  return
@@ -1309,9 +1318,9 @@ class GuiDocEditor(QPlainTextEdit):
1309
1318
  if len(resS) == 0 and self._docHandle:
1310
1319
  self.docSearch.setResultCount(0, 0)
1311
1320
  self._lastFind = None
1312
- if self.docSearch.doNextFile and not goBack:
1321
+ if CONFIG.searchNextFile and not goBack:
1313
1322
  self.mainGui.openNextDocument(
1314
- self._docHandle, wrapAround=self.docSearch.doLoop
1323
+ self._docHandle, wrapAround=CONFIG.searchLoop
1315
1324
  )
1316
1325
  self.beginSearch()
1317
1326
  self.setFocus()
@@ -1320,7 +1329,7 @@ class GuiDocEditor(QPlainTextEdit):
1320
1329
  cursor = self.textCursor()
1321
1330
  resIdx = bisect.bisect_left(resS, cursor.position())
1322
1331
 
1323
- doLoop = self.docSearch.doLoop
1332
+ doLoop = CONFIG.searchLoop
1324
1333
  maxIdx = len(resS) - 1
1325
1334
 
1326
1335
  if goBack:
@@ -1330,9 +1339,9 @@ class GuiDocEditor(QPlainTextEdit):
1330
1339
  resIdx = maxIdx if doLoop else 0
1331
1340
 
1332
1341
  if resIdx > maxIdx and self._docHandle:
1333
- if self.docSearch.doNextFile and not goBack:
1342
+ if CONFIG.searchNextFile and not goBack:
1334
1343
  self.mainGui.openNextDocument(
1335
- self._docHandle, wrapAround=self.docSearch.doLoop
1344
+ self._docHandle, wrapAround=CONFIG.searchLoop
1336
1345
  )
1337
1346
  self.beginSearch()
1338
1347
  self.setFocus()
@@ -1340,8 +1349,8 @@ class GuiDocEditor(QPlainTextEdit):
1340
1349
  else:
1341
1350
  resIdx = 0 if doLoop else maxIdx
1342
1351
 
1343
- cursor.setPosition(resS[resIdx], QTextCursor.MoveMode.MoveAnchor)
1344
- cursor.setPosition(resE[resIdx], QTextCursor.MoveMode.KeepAnchor)
1352
+ cursor.setPosition(resS[resIdx], QtMoveAnchor)
1353
+ cursor.setPosition(resE[resIdx], QtKeepAnchor)
1345
1354
  self.setTextCursor(cursor)
1346
1355
 
1347
1356
  self.docSearch.setResultCount(resIdx + 1, len(resS))
@@ -1365,9 +1374,9 @@ class GuiDocEditor(QPlainTextEdit):
1365
1374
  origB = cursor.position()
1366
1375
 
1367
1376
  findOpt = QTextDocument.FindFlag(0)
1368
- if self.docSearch.isCaseSense:
1377
+ if CONFIG.searchCase:
1369
1378
  findOpt |= QTextDocument.FindFlag.FindCaseSensitively
1370
- if self.docSearch.isWholeWord:
1379
+ if CONFIG.searchWord:
1371
1380
  findOpt |= QTextDocument.FindFlag.FindWholeWords
1372
1381
 
1373
1382
  searchFor = self.docSearch.getSearchObject()
@@ -1387,8 +1396,8 @@ class GuiDocEditor(QPlainTextEdit):
1387
1396
  break
1388
1397
 
1389
1398
  if hasSelection:
1390
- cursor.setPosition(origA, QTextCursor.MoveMode.MoveAnchor)
1391
- cursor.setPosition(origB, QTextCursor.MoveMode.KeepAnchor)
1399
+ cursor.setPosition(origA, QtMoveAnchor)
1400
+ cursor.setPosition(origB, QtKeepAnchor)
1392
1401
  else:
1393
1402
  cursor.setPosition(origA)
1394
1403
 
@@ -1436,7 +1445,7 @@ class GuiDocEditor(QPlainTextEdit):
1436
1445
  searchFor = self.docSearch.searchText
1437
1446
  replWith = self.docSearch.replaceText
1438
1447
 
1439
- if self.docSearch.doMatchCap:
1448
+ if CONFIG.searchMatchCap:
1440
1449
  replWith = transferCase(cursor.selectedText(), replWith)
1441
1450
 
1442
1451
  # Make sure the selected text was selected by an actual find
@@ -1491,8 +1500,8 @@ class GuiDocEditor(QPlainTextEdit):
1491
1500
  if blockS != blockE:
1492
1501
  posE = blockS.position() + blockS.length() - 1
1493
1502
  cursor.clearSelection()
1494
- cursor.setPosition(posS, QTextCursor.MoveMode.MoveAnchor)
1495
- cursor.setPosition(posE, QTextCursor.MoveMode.KeepAnchor)
1503
+ cursor.setPosition(posS, QtMoveAnchor)
1504
+ cursor.setPosition(posE, QtKeepAnchor)
1496
1505
  self.setTextCursor(cursor)
1497
1506
 
1498
1507
  numB = 0
@@ -1569,8 +1578,8 @@ class GuiDocEditor(QPlainTextEdit):
1569
1578
  if select == _SelectAction.MOVE_AFTER:
1570
1579
  cursor.setPosition(posE + len(before + after))
1571
1580
  elif select == _SelectAction.KEEP_SELECTION:
1572
- cursor.setPosition(posE + len(before), QTextCursor.MoveMode.MoveAnchor)
1573
- cursor.setPosition(posS + len(before), QTextCursor.MoveMode.KeepAnchor)
1581
+ cursor.setPosition(posE + len(before), QtMoveAnchor)
1582
+ cursor.setPosition(posS + len(before), QtKeepAnchor)
1574
1583
  elif select == _SelectAction.KEEP_POSITION:
1575
1584
  cursor.setPosition(posO + len(before))
1576
1585
 
@@ -1592,9 +1601,7 @@ class GuiDocEditor(QPlainTextEdit):
1592
1601
  self._allowAutoReplace(False)
1593
1602
  for posC in range(posS, posE+1):
1594
1603
  cursor.setPosition(posC)
1595
- cursor.movePosition(
1596
- QTextCursor.MoveOperation.Left, QTextCursor.MoveMode.KeepAnchor, 2
1597
- )
1604
+ cursor.movePosition(QtMoveLeft, QtKeepAnchor, 2)
1598
1605
  selText = cursor.selectedText()
1599
1606
 
1600
1607
  nS = len(selText)
@@ -1614,16 +1621,12 @@ class GuiDocEditor(QPlainTextEdit):
1614
1621
  cursor.setPosition(posC)
1615
1622
  if pC in closeCheck:
1616
1623
  cursor.beginEditBlock()
1617
- cursor.movePosition(
1618
- QTextCursor.MoveOperation.Left, QTextCursor.MoveMode.KeepAnchor, 1
1619
- )
1624
+ cursor.movePosition(QtMoveLeft, QtKeepAnchor, 1)
1620
1625
  cursor.insertText(oQuote)
1621
1626
  cursor.endEditBlock()
1622
1627
  else:
1623
1628
  cursor.beginEditBlock()
1624
- cursor.movePosition(
1625
- QTextCursor.MoveOperation.Left, QTextCursor.MoveMode.KeepAnchor, 1
1626
- )
1629
+ cursor.movePosition(QtMoveLeft, QtKeepAnchor, 1)
1627
1630
  cursor.insertText(cQuote)
1628
1631
  cursor.endEditBlock()
1629
1632
 
@@ -1839,9 +1842,7 @@ class GuiDocEditor(QPlainTextEdit):
1839
1842
  cursor.beginEditBlock()
1840
1843
  cursor.clearSelection()
1841
1844
  cursor.setPosition(rS)
1842
- cursor.movePosition(
1843
- QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor, rE-rS
1844
- )
1845
+ cursor.movePosition(QtMoveRight, QtKeepAnchor, rE-rS)
1845
1846
  cursor.insertText(cleanText.rstrip() + "\n")
1846
1847
  cursor.endEditBlock()
1847
1848
 
@@ -1902,7 +1903,7 @@ class GuiDocEditor(QPlainTextEdit):
1902
1903
  ).format(tag)):
1903
1904
  itemClass = nwKeyWords.KEY_CLASS.get(tBits[0], nwItemClass.NO_CLASS)
1904
1905
  self.requestNewNoteCreation.emit(tag, itemClass)
1905
- qApp.processEvents()
1906
+ QApplication.processEvents()
1906
1907
  self._qDocument.syntaxHighlighter.rehighlightBlock(block)
1907
1908
 
1908
1909
  return nwTrinary.POSITIVE if exist else nwTrinary.NEGATIVE
@@ -2007,9 +2008,7 @@ class GuiDocEditor(QPlainTextEdit):
2007
2008
  tInsert = tInsert + self._typPadChar
2008
2009
 
2009
2010
  if nDelete > 0:
2010
- cursor.movePosition(
2011
- QTextCursor.MoveOperation.Left, QTextCursor.MoveMode.KeepAnchor, nDelete
2012
- )
2011
+ cursor.movePosition(QtMoveLeft, QtKeepAnchor, nDelete)
2013
2012
  cursor.insertText(tInsert)
2014
2013
 
2015
2014
  return
@@ -2065,8 +2064,8 @@ class GuiDocEditor(QPlainTextEdit):
2065
2064
  return cursor
2066
2065
 
2067
2066
  cursor.clearSelection()
2068
- cursor.setPosition(sPos, QTextCursor.MoveMode.MoveAnchor)
2069
- cursor.setPosition(ePos, QTextCursor.MoveMode.KeepAnchor)
2067
+ cursor.setPosition(sPos, QtMoveAnchor)
2068
+ cursor.setPosition(ePos, QtKeepAnchor)
2070
2069
 
2071
2070
  self.setTextCursor(cursor)
2072
2071
 
@@ -2090,8 +2089,8 @@ class GuiDocEditor(QPlainTextEdit):
2090
2089
  posE = cursor.selectionEnd()
2091
2090
  selTxt = cursor.selectedText()
2092
2091
  if selTxt.startswith(nwUnicode.U_PSEP):
2093
- cursor.setPosition(posS+1, QTextCursor.MoveMode.MoveAnchor)
2094
- cursor.setPosition(posE, QTextCursor.MoveMode.KeepAnchor)
2092
+ cursor.setPosition(posS+1, QtMoveAnchor)
2093
+ cursor.setPosition(posE, QtKeepAnchor)
2095
2094
 
2096
2095
  self.setTextCursor(cursor)
2097
2096
 
@@ -2222,7 +2221,7 @@ class BackgroundWordCounter(QRunnable):
2222
2221
  """
2223
2222
  self._isRunning = True
2224
2223
  if self._forSelection:
2225
- text = self._docEditor.textCursor().selectedText()
2224
+ text = self._docEditor.getSelectedText()
2226
2225
  else:
2227
2226
  text = self._docEditor.getText()
2228
2227
 
@@ -2258,79 +2257,68 @@ class GuiDocToolBar(QWidget):
2258
2257
 
2259
2258
  logger.debug("Create: GuiDocToolBar")
2260
2259
 
2260
+ iSz = SHARED.theme.baseIconSize
2261
2261
  cM = CONFIG.pxInt(4)
2262
- tPx = int(0.8*SHARED.theme.fontPixelSize)
2263
- iconSize = QSize(tPx, tPx)
2264
2262
  self.setContentsMargins(0, 0, 0, 0)
2265
2263
 
2266
2264
  # General Buttons
2267
2265
  # ===============
2268
2266
 
2269
- self.tbBoldMD = QToolButton(self)
2270
- self.tbBoldMD.setIconSize(iconSize)
2267
+ self.tbBoldMD = NIconToolButton(self, iSz)
2271
2268
  self.tbBoldMD.setToolTip(self.tr("Markdown Bold"))
2272
2269
  self.tbBoldMD.clicked.connect(
2273
2270
  lambda: self.requestDocAction.emit(nwDocAction.MD_BOLD)
2274
2271
  )
2275
2272
 
2276
- self.tbItalicMD = QToolButton(self)
2277
- self.tbItalicMD.setIconSize(iconSize)
2273
+ self.tbItalicMD = NIconToolButton(self, iSz)
2278
2274
  self.tbItalicMD.setToolTip(self.tr("Markdown Italic"))
2279
2275
  self.tbItalicMD.clicked.connect(
2280
2276
  lambda: self.requestDocAction.emit(nwDocAction.MD_ITALIC)
2281
2277
  )
2282
2278
 
2283
- self.tbStrikeMD = QToolButton(self)
2284
- self.tbStrikeMD.setIconSize(iconSize)
2279
+ self.tbStrikeMD = NIconToolButton(self, iSz)
2285
2280
  self.tbStrikeMD.setToolTip(self.tr("Markdown Strikethrough"))
2286
2281
  self.tbStrikeMD.clicked.connect(
2287
2282
  lambda: self.requestDocAction.emit(nwDocAction.MD_STRIKE)
2288
2283
  )
2289
2284
 
2290
- self.tbBold = QToolButton(self)
2291
- self.tbBold.setIconSize(iconSize)
2285
+ self.tbBold = NIconToolButton(self, iSz)
2292
2286
  self.tbBold.setToolTip(self.tr("Shortcode Bold"))
2293
2287
  self.tbBold.clicked.connect(
2294
2288
  lambda: self.requestDocAction.emit(nwDocAction.SC_BOLD)
2295
2289
  )
2296
2290
 
2297
- self.tbItalic = QToolButton(self)
2298
- self.tbItalic.setIconSize(iconSize)
2291
+ self.tbItalic = NIconToolButton(self, iSz)
2299
2292
  self.tbItalic.setToolTip(self.tr("Shortcode Italic"))
2300
2293
  self.tbItalic.clicked.connect(
2301
2294
  lambda: self.requestDocAction.emit(nwDocAction.SC_ITALIC)
2302
2295
  )
2303
2296
 
2304
- self.tbStrike = QToolButton(self)
2305
- self.tbStrike.setIconSize(iconSize)
2297
+ self.tbStrike = NIconToolButton(self, iSz)
2306
2298
  self.tbStrike.setToolTip(self.tr("Shortcode Strikethrough"))
2307
2299
  self.tbStrike.clicked.connect(
2308
2300
  lambda: self.requestDocAction.emit(nwDocAction.SC_STRIKE)
2309
2301
  )
2310
2302
 
2311
- self.tbUnderline = QToolButton(self)
2312
- self.tbUnderline.setIconSize(iconSize)
2303
+ self.tbUnderline = NIconToolButton(self, iSz)
2313
2304
  self.tbUnderline.setToolTip(self.tr("Shortcode Underline"))
2314
2305
  self.tbUnderline.clicked.connect(
2315
2306
  lambda: self.requestDocAction.emit(nwDocAction.SC_ULINE)
2316
2307
  )
2317
2308
 
2318
- self.tbMark = QToolButton(self)
2319
- self.tbMark.setIconSize(iconSize)
2309
+ self.tbMark = NIconToolButton(self, iSz)
2320
2310
  self.tbMark.setToolTip(self.tr("Shortcode Highlight"))
2321
2311
  self.tbMark.clicked.connect(
2322
2312
  lambda: self.requestDocAction.emit(nwDocAction.SC_MARK)
2323
2313
  )
2324
2314
 
2325
- self.tbSuperscript = QToolButton(self)
2326
- self.tbSuperscript.setIconSize(iconSize)
2315
+ self.tbSuperscript = NIconToolButton(self, iSz)
2327
2316
  self.tbSuperscript.setToolTip(self.tr("Shortcode Superscript"))
2328
2317
  self.tbSuperscript.clicked.connect(
2329
2318
  lambda: self.requestDocAction.emit(nwDocAction.SC_SUP)
2330
2319
  )
2331
2320
 
2332
- self.tbSubscript = QToolButton(self)
2333
- self.tbSubscript.setIconSize(iconSize)
2321
+ self.tbSubscript = NIconToolButton(self, iSz)
2334
2322
  self.tbSubscript.setToolTip(self.tr("Shortcode Subscript"))
2335
2323
  self.tbSubscript.clicked.connect(
2336
2324
  lambda: self.requestDocAction.emit(nwDocAction.SC_SUB)
@@ -2372,16 +2360,16 @@ class GuiDocToolBar(QWidget):
2372
2360
  palette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
2373
2361
  self.setPalette(palette)
2374
2362
 
2375
- self.tbBoldMD.setIcon(SHARED.theme.getIcon("fmt_bold-md"))
2376
- self.tbItalicMD.setIcon(SHARED.theme.getIcon("fmt_italic-md"))
2377
- self.tbStrikeMD.setIcon(SHARED.theme.getIcon("fmt_strike-md"))
2378
- self.tbBold.setIcon(SHARED.theme.getIcon("fmt_bold"))
2379
- self.tbItalic.setIcon(SHARED.theme.getIcon("fmt_italic"))
2380
- self.tbStrike.setIcon(SHARED.theme.getIcon("fmt_strike"))
2381
- self.tbUnderline.setIcon(SHARED.theme.getIcon("fmt_underline"))
2382
- self.tbMark.setIcon(SHARED.theme.getIcon("fmt_mark"))
2383
- self.tbSuperscript.setIcon(SHARED.theme.getIcon("fmt_superscript"))
2384
- self.tbSubscript.setIcon(SHARED.theme.getIcon("fmt_subscript"))
2363
+ self.tbBoldMD.setThemeIcon("fmt_bold-md")
2364
+ self.tbItalicMD.setThemeIcon("fmt_italic-md")
2365
+ self.tbStrikeMD.setThemeIcon("fmt_strike-md")
2366
+ self.tbBold.setThemeIcon("fmt_bold")
2367
+ self.tbItalic.setThemeIcon("fmt_italic")
2368
+ self.tbStrike.setThemeIcon("fmt_strike")
2369
+ self.tbUnderline.setThemeIcon("fmt_underline")
2370
+ self.tbMark.setThemeIcon("fmt_mark")
2371
+ self.tbSuperscript.setThemeIcon("fmt_superscript")
2372
+ self.tbSubscript.setThemeIcon("fmt_subscript")
2385
2373
 
2386
2374
  return
2387
2375
 
@@ -2402,16 +2390,9 @@ class GuiDocEditSearch(QFrame):
2402
2390
 
2403
2391
  self.docEditor = docEditor
2404
2392
 
2405
- self.repVisible = False
2406
- self.isCaseSense = CONFIG.searchCase
2407
- self.isWholeWord = CONFIG.searchWord
2408
- self.isRegEx = CONFIG.searchRegEx
2409
- self.doLoop = CONFIG.searchLoop
2410
- self.doNextFile = CONFIG.searchNextFile
2411
- self.doMatchCap = CONFIG.searchMatchCap
2412
-
2393
+ iSz = SHARED.theme.baseIconSize
2413
2394
  mPx = CONFIG.pxInt(6)
2414
- tPx = int(0.8*SHARED.theme.fontPixelSize)
2395
+
2415
2396
  self.boxFont = SHARED.theme.guiFont
2416
2397
  self.boxFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
2417
2398
 
@@ -2437,44 +2418,44 @@ class GuiDocEditSearch(QFrame):
2437
2418
 
2438
2419
  self.searchOpt = QToolBar(self)
2439
2420
  self.searchOpt.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
2440
- self.searchOpt.setIconSize(QSize(tPx, tPx))
2421
+ self.searchOpt.setIconSize(iSz)
2441
2422
  self.searchOpt.setContentsMargins(0, 0, 0, 0)
2442
2423
 
2443
- self.searchLabel = QLabel(self.tr("Search"))
2424
+ self.searchLabel = QLabel(self.tr("Search"), self)
2444
2425
  self.searchLabel.setFont(self.boxFont)
2445
2426
  self.searchLabel.setIndent(CONFIG.pxInt(6))
2446
2427
 
2447
- self.resultLabel = QLabel("?/?")
2428
+ self.resultLabel = QLabel("?/?", self)
2448
2429
  self.resultLabel.setFont(self.boxFont)
2449
2430
  self.resultLabel.setMinimumWidth(SHARED.theme.getTextWidth("?/?", self.boxFont))
2450
2431
 
2451
2432
  self.toggleCase = QAction(self.tr("Case Sensitive"), self)
2452
2433
  self.toggleCase.setCheckable(True)
2453
- self.toggleCase.setChecked(self.isCaseSense)
2434
+ self.toggleCase.setChecked(CONFIG.searchCase)
2454
2435
  self.toggleCase.toggled.connect(self._doToggleCase)
2455
2436
  self.searchOpt.addAction(self.toggleCase)
2456
2437
 
2457
2438
  self.toggleWord = QAction(self.tr("Whole Words Only"), self)
2458
2439
  self.toggleWord.setCheckable(True)
2459
- self.toggleWord.setChecked(self.isWholeWord)
2440
+ self.toggleWord.setChecked(CONFIG.searchWord)
2460
2441
  self.toggleWord.toggled.connect(self._doToggleWord)
2461
2442
  self.searchOpt.addAction(self.toggleWord)
2462
2443
 
2463
2444
  self.toggleRegEx = QAction(self.tr("RegEx Mode"), self)
2464
2445
  self.toggleRegEx.setCheckable(True)
2465
- self.toggleRegEx.setChecked(self.isRegEx)
2446
+ self.toggleRegEx.setChecked(CONFIG.searchRegEx)
2466
2447
  self.toggleRegEx.toggled.connect(self._doToggleRegEx)
2467
2448
  self.searchOpt.addAction(self.toggleRegEx)
2468
2449
 
2469
2450
  self.toggleLoop = QAction(self.tr("Loop Search"), self)
2470
2451
  self.toggleLoop.setCheckable(True)
2471
- self.toggleLoop.setChecked(self.doLoop)
2452
+ self.toggleLoop.setChecked(CONFIG.searchLoop)
2472
2453
  self.toggleLoop.toggled.connect(self._doToggleLoop)
2473
2454
  self.searchOpt.addAction(self.toggleLoop)
2474
2455
 
2475
2456
  self.toggleProject = QAction(self.tr("Search Next File"), self)
2476
2457
  self.toggleProject.setCheckable(True)
2477
- self.toggleProject.setChecked(self.doNextFile)
2458
+ self.toggleProject.setChecked(CONFIG.searchNextFile)
2478
2459
  self.toggleProject.toggled.connect(self._doToggleProject)
2479
2460
  self.searchOpt.addAction(self.toggleProject)
2480
2461
 
@@ -2482,38 +2463,32 @@ class GuiDocEditSearch(QFrame):
2482
2463
 
2483
2464
  self.toggleMatchCap = QAction(self.tr("Preserve Case"), self)
2484
2465
  self.toggleMatchCap.setCheckable(True)
2485
- self.toggleMatchCap.setChecked(self.doMatchCap)
2466
+ self.toggleMatchCap.setChecked(CONFIG.searchMatchCap)
2486
2467
  self.toggleMatchCap.toggled.connect(self._doToggleMatchCap)
2487
2468
  self.searchOpt.addAction(self.toggleMatchCap)
2488
2469
 
2489
2470
  self.searchOpt.addSeparator()
2490
2471
 
2491
2472
  self.cancelSearch = QAction(self.tr("Close Search"), self)
2492
- self.cancelSearch.triggered.connect(self._doClose)
2473
+ self.cancelSearch.triggered.connect(self.closeSearch)
2493
2474
  self.searchOpt.addAction(self.cancelSearch)
2494
2475
 
2495
2476
  # Buttons
2496
2477
  # =======
2497
2478
 
2498
- bPx = self.searchBox.sizeHint().height()
2499
-
2500
- self.showReplace = QToolButton(self)
2501
- self.showReplace.setArrowType(Qt.ArrowType.RightArrow)
2502
- self.showReplace.setCheckable(True)
2479
+ self.showReplace = NIconToggleButton(self, iSz, "unfold")
2503
2480
  self.showReplace.toggled.connect(self._doToggleReplace)
2504
2481
 
2505
- self.searchButton = QPushButton("")
2506
- self.searchButton.setFixedSize(QSize(bPx, bPx))
2482
+ self.searchButton = NIconToolButton(self, iSz)
2507
2483
  self.searchButton.setToolTip(self.tr("Find in current document"))
2508
2484
  self.searchButton.clicked.connect(self._doSearch)
2509
2485
 
2510
- self.replaceButton = QPushButton("")
2511
- self.replaceButton.setFixedSize(QSize(bPx, bPx))
2486
+ self.replaceButton = NIconToolButton(self, iSz)
2512
2487
  self.replaceButton.setToolTip(self.tr("Find and replace in current document"))
2513
2488
  self.replaceButton.clicked.connect(self._doReplace)
2514
2489
 
2515
- self.mainBox.addWidget(self.searchLabel, 0, 0, 1, 2, Qt.AlignmentFlag.AlignLeft)
2516
- self.mainBox.addWidget(self.searchOpt, 0, 2, 1, 3, Qt.AlignmentFlag.AlignRight)
2490
+ self.mainBox.addWidget(self.searchLabel, 0, 0, 1, 2, QtAlignLeft)
2491
+ self.mainBox.addWidget(self.searchOpt, 0, 2, 1, 3, QtAlignRight)
2517
2492
  self.mainBox.addWidget(self.showReplace, 1, 0, 1, 1)
2518
2493
  self.mainBox.addWidget(self.searchBox, 1, 1, 1, 2)
2519
2494
  self.mainBox.addWidget(self.searchButton, 1, 3, 1, 1)
@@ -2566,20 +2541,20 @@ class GuiDocEditSearch(QFrame):
2566
2541
  expression object.
2567
2542
  """
2568
2543
  text = self.searchBox.text()
2569
- if self.isRegEx:
2544
+ if CONFIG.searchRegEx:
2570
2545
  # Using the Unicode-capable QRegularExpression class was
2571
2546
  # only added in Qt 5.13. Otherwise, 5.3 and up supports
2572
2547
  # only the QRegExp class.
2573
2548
  if CONFIG.verQtValue >= 0x050d00:
2574
2549
  rxOpt = QRegularExpression.PatternOption.UseUnicodePropertiesOption
2575
- if not self.isCaseSense:
2550
+ if not CONFIG.searchCase:
2576
2551
  rxOpt |= QRegularExpression.PatternOption.CaseInsensitiveOption
2577
2552
  regEx = QRegularExpression(text, rxOpt)
2578
2553
  self._alertSearchValid(regEx.isValid())
2579
2554
  return regEx
2580
2555
  else: # pragma: no cover
2581
2556
  # >= 50300 to < 51300
2582
- if self.isCaseSense:
2557
+ if CONFIG.searchCase:
2583
2558
  rxOpt = Qt.CaseSensitivity.CaseSensitive
2584
2559
  else:
2585
2560
  rxOpt = Qt.CaseSensitivity.CaseInsensitive
@@ -2603,7 +2578,7 @@ class GuiDocEditSearch(QFrame):
2603
2578
  self.searchBox.setText(text)
2604
2579
  self.searchBox.setFocus()
2605
2580
  self.searchBox.selectAll()
2606
- if self.isRegEx:
2581
+ if CONFIG.searchRegEx:
2607
2582
  self._alertSearchValid(True)
2608
2583
  return
2609
2584
 
@@ -2633,7 +2608,7 @@ class GuiDocEditSearch(QFrame):
2633
2608
 
2634
2609
  def updateTheme(self) -> None:
2635
2610
  """Update theme elements."""
2636
- qPalette = qApp.palette()
2611
+ qPalette = QApplication.palette()
2637
2612
  self.setPalette(qPalette)
2638
2613
  self.searchBox.setPalette(qPalette)
2639
2614
  self.replaceBox.setPalette(qPalette)
@@ -2646,8 +2621,8 @@ class GuiDocEditSearch(QFrame):
2646
2621
  self.toggleProject.setIcon(SHARED.theme.getIcon("search_project"))
2647
2622
  self.toggleMatchCap.setIcon(SHARED.theme.getIcon("search_preserve"))
2648
2623
  self.cancelSearch.setIcon(SHARED.theme.getIcon("search_cancel"))
2649
- self.searchButton.setIcon(SHARED.theme.getIcon("search"))
2650
- self.replaceButton.setIcon(SHARED.theme.getIcon("search_replace"))
2624
+ self.searchButton.setThemeIcon("search")
2625
+ self.replaceButton.setThemeIcon("search_replace")
2651
2626
 
2652
2627
  # Set stylesheets
2653
2628
  self.searchOpt.setStyleSheet("QToolBar {padding: 0;}")
@@ -2673,55 +2648,43 @@ class GuiDocEditSearch(QFrame):
2673
2648
 
2674
2649
  return
2675
2650
 
2676
- def closeSearch(self) -> None:
2677
- """Close the search box."""
2678
- CONFIG.searchCase = self.isCaseSense
2679
- CONFIG.searchWord = self.isWholeWord
2680
- CONFIG.searchRegEx = self.isRegEx
2681
- CONFIG.searchLoop = self.doLoop
2682
- CONFIG.searchNextFile = self.doNextFile
2683
- CONFIG.searchMatchCap = self.doMatchCap
2684
-
2685
- self.showReplace.setChecked(False)
2686
- self.setVisible(False)
2687
- self.docEditor.updateDocMargins()
2688
- self.docEditor.setFocus()
2689
-
2690
- return
2691
-
2692
- def cycleFocus(self, next: bool) -> bool:
2651
+ def cycleFocus(self) -> bool:
2693
2652
  """The tab key just alternates focus between the two input
2694
2653
  boxes, if the replace box is visible.
2695
2654
  """
2696
- if self.replaceBox.isVisible():
2697
- if self.searchBox.hasFocus():
2698
- self.replaceBox.setFocus()
2699
- return True
2700
- elif self.replaceBox.hasFocus():
2701
- self.searchBox.setFocus()
2702
- return True
2655
+ if self.searchBox.hasFocus():
2656
+ self.replaceBox.setFocus()
2657
+ return True
2658
+ elif self.replaceBox.hasFocus():
2659
+ self.searchBox.setFocus()
2660
+ return True
2703
2661
  return False
2704
2662
 
2705
2663
  def anyFocus(self) -> bool:
2706
2664
  """Return True if any of the input boxes have focus."""
2707
- return self.searchBox.hasFocus() | self.replaceBox.hasFocus()
2665
+ return self.searchBox.hasFocus() or self.replaceBox.hasFocus()
2708
2666
 
2709
2667
  ##
2710
- # Private Slots
2668
+ # Public Slots
2711
2669
  ##
2712
2670
 
2713
2671
  @pyqtSlot()
2714
- def _doClose(self) -> None:
2715
- """Hide the search/replace bar."""
2716
- self.closeSearch()
2672
+ def closeSearch(self) -> None:
2673
+ """Close the search box."""
2674
+ self.showReplace.setChecked(False)
2675
+ self.setVisible(False)
2676
+ self.docEditor.updateDocMargins()
2677
+ self.docEditor.setFocus()
2717
2678
  return
2718
2679
 
2680
+ ##
2681
+ # Private Slots
2682
+ ##
2683
+
2719
2684
  @pyqtSlot()
2720
2685
  def _doSearch(self) -> None:
2721
2686
  """Call the search action function for the document editor."""
2722
- self.docEditor.findNext(goBack=(
2723
- qApp.keyboardModifiers() == Qt.KeyboardModifier.ShiftModifier)
2724
- )
2687
+ self.docEditor.findNext(goBack=(QApplication.keyboardModifiers() == QtModShift))
2725
2688
  return
2726
2689
 
2727
2690
  @pyqtSlot()
@@ -2733,13 +2696,8 @@ class GuiDocEditSearch(QFrame):
2733
2696
  @pyqtSlot(bool)
2734
2697
  def _doToggleReplace(self, state: bool) -> None:
2735
2698
  """Toggle the show/hide of the replace box."""
2736
- if state:
2737
- self.showReplace.setArrowType(Qt.ArrowType.DownArrow)
2738
- else:
2739
- self.showReplace.setArrowType(Qt.ArrowType.RightArrow)
2740
2699
  self.replaceBox.setVisible(state)
2741
2700
  self.replaceButton.setVisible(state)
2742
- self.repVisible = state
2743
2701
  self.adjustSize()
2744
2702
  self.docEditor.updateDocMargins()
2745
2703
  return
@@ -2747,37 +2705,37 @@ class GuiDocEditSearch(QFrame):
2747
2705
  @pyqtSlot(bool)
2748
2706
  def _doToggleCase(self, state: bool) -> None:
2749
2707
  """Enable/disable case sensitive mode."""
2750
- self.isCaseSense = state
2708
+ CONFIG.searchCase = state
2751
2709
  return
2752
2710
 
2753
2711
  @pyqtSlot(bool)
2754
2712
  def _doToggleWord(self, state: bool) -> None:
2755
2713
  """Enable/disable whole word search mode."""
2756
- self.isWholeWord = state
2714
+ CONFIG.searchWord = state
2757
2715
  return
2758
2716
 
2759
2717
  @pyqtSlot(bool)
2760
2718
  def _doToggleRegEx(self, state: bool) -> None:
2761
2719
  """Enable/disable regular expression search mode."""
2762
- self.isRegEx = state
2720
+ CONFIG.searchRegEx = state
2763
2721
  return
2764
2722
 
2765
2723
  @pyqtSlot(bool)
2766
2724
  def _doToggleLoop(self, state: bool) -> None:
2767
2725
  """Enable/disable looping the search."""
2768
- self.doLoop = state
2726
+ CONFIG.searchLoop = state
2769
2727
  return
2770
2728
 
2771
2729
  @pyqtSlot(bool)
2772
2730
  def _doToggleProject(self, state: bool) -> None:
2773
2731
  """Enable/disable continuing search in next project file."""
2774
- self.doNextFile = state
2732
+ CONFIG.searchNextFile = state
2775
2733
  return
2776
2734
 
2777
2735
  @pyqtSlot(bool)
2778
2736
  def _doToggleMatchCap(self, state: bool) -> None:
2779
2737
  """Enable/disable preserving capitalisation when replacing."""
2780
- self.doMatchCap = state
2738
+ CONFIG.searchMatchCap = state
2781
2739
  return
2782
2740
 
2783
2741
  ##
@@ -2816,7 +2774,8 @@ class GuiDocEditHeader(QWidget):
2816
2774
  self._docHandle = None
2817
2775
  self._docOutline: dict[int, str] = {}
2818
2776
 
2819
- iPx = SHARED.theme.baseIconSize
2777
+ iPx = SHARED.theme.baseIconHeight
2778
+ iSz = SHARED.theme.baseIconSize
2820
2779
  mPx = CONFIG.pxInt(4)
2821
2780
 
2822
2781
  # Main Widget Settings
@@ -2828,7 +2787,7 @@ class GuiDocEditHeader(QWidget):
2828
2787
  self.itemTitle.setMargin(0)
2829
2788
  self.itemTitle.setContentsMargins(0, 0, 0, 0)
2830
2789
  self.itemTitle.setAutoFillBackground(True)
2831
- self.itemTitle.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop)
2790
+ self.itemTitle.setAlignment(QtAlignCenterTop)
2832
2791
  self.itemTitle.setFixedHeight(iPx)
2833
2792
 
2834
2793
  lblFont = self.itemTitle.font()
@@ -2839,27 +2798,27 @@ class GuiDocEditHeader(QWidget):
2839
2798
  self.outlineMenu = QMenu(self)
2840
2799
 
2841
2800
  # Buttons
2842
- self.tbButton = NIconToolButton(self, iPx)
2801
+ self.tbButton = NIconToolButton(self, iSz)
2843
2802
  self.tbButton.setVisible(False)
2844
2803
  self.tbButton.setToolTip(self.tr("Toggle Tool Bar"))
2845
2804
  self.tbButton.clicked.connect(lambda: self.toggleToolBarRequest.emit())
2846
2805
 
2847
- self.outlineButton = NIconToolButton(self, iPx)
2806
+ self.outlineButton = NIconToolButton(self, iSz)
2848
2807
  self.outlineButton.setVisible(False)
2849
2808
  self.outlineButton.setToolTip(self.tr("Outline"))
2850
2809
  self.outlineButton.setMenu(self.outlineMenu)
2851
2810
 
2852
- self.searchButton = NIconToolButton(self, iPx)
2811
+ self.searchButton = NIconToolButton(self, iSz)
2853
2812
  self.searchButton.setVisible(False)
2854
2813
  self.searchButton.setToolTip(self.tr("Search"))
2855
2814
  self.searchButton.clicked.connect(self.docEditor.toggleSearch)
2856
2815
 
2857
- self.minmaxButton = NIconToolButton(self, iPx)
2816
+ self.minmaxButton = NIconToolButton(self, iSz)
2858
2817
  self.minmaxButton.setVisible(False)
2859
2818
  self.minmaxButton.setToolTip(self.tr("Toggle Focus Mode"))
2860
2819
  self.minmaxButton.clicked.connect(lambda: self.docEditor.toggleFocusModeRequest.emit())
2861
2820
 
2862
- self.closeButton = NIconToolButton(self, iPx)
2821
+ self.closeButton = NIconToolButton(self, iSz)
2863
2822
  self.closeButton.setVisible(False)
2864
2823
  self.closeButton.setToolTip(self.tr("Close"))
2865
2824
  self.closeButton.clicked.connect(self._closeDocument)
@@ -2928,11 +2887,11 @@ class GuiDocEditHeader(QWidget):
2928
2887
 
2929
2888
  def updateTheme(self) -> None:
2930
2889
  """Update theme elements."""
2931
- self.tbButton.setIcon(SHARED.theme.getIcon("menu"))
2932
- self.outlineButton.setIcon(SHARED.theme.getIcon("list"))
2933
- self.searchButton.setIcon(SHARED.theme.getIcon("search"))
2934
- self.minmaxButton.setIcon(SHARED.theme.getIcon("maximise"))
2935
- self.closeButton.setIcon(SHARED.theme.getIcon("close"))
2890
+ self.tbButton.setThemeIcon("menu")
2891
+ self.outlineButton.setThemeIcon("list")
2892
+ self.searchButton.setThemeIcon("search")
2893
+ self.minmaxButton.setThemeIcon("maximise")
2894
+ self.closeButton.setThemeIcon("close")
2936
2895
 
2937
2896
  buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
2938
2897
  self.tbButton.setStyleSheet(buttonStyle)
@@ -3000,7 +2959,7 @@ class GuiDocEditHeader(QWidget):
3000
2959
  @pyqtSlot(bool)
3001
2960
  def _focusModeChanged(self, focusMode: bool) -> None:
3002
2961
  """Update minimise/maximise icon of the Focus Mode button."""
3003
- self.minmaxButton.setIcon(SHARED.theme.getIcon("minimise" if focusMode else "maximise"))
2962
+ self.minmaxButton.setThemeIcon("minimise" if focusMode else "maximise")
3004
2963
  return
3005
2964
 
3006
2965
  ##
@@ -3011,7 +2970,7 @@ class GuiDocEditHeader(QWidget):
3011
2970
  """Capture a click on the title and ensure that the item is
3012
2971
  selected in the project tree.
3013
2972
  """
3014
- if event.button() == Qt.MouseButton.LeftButton:
2973
+ if event.button() == QtMouseLeft:
3015
2974
  self.docEditor.requestProjectItemSelected.emit(self._docHandle or "", True)
3016
2975
  return
3017
2976
 
@@ -3033,7 +2992,7 @@ class GuiDocEditFooter(QWidget):
3033
2992
  self._tItem = None
3034
2993
  self._docHandle = None
3035
2994
 
3036
- iPx = round(0.9*SHARED.theme.baseIconSize)
2995
+ iPx = round(0.9*SHARED.theme.baseIconHeight)
3037
2996
  fPx = int(0.9*SHARED.theme.fontPixelSize)
3038
2997
  mPx = CONFIG.pxInt(8)
3039
2998
  bSp = CONFIG.pxInt(4)
@@ -3051,28 +3010,26 @@ class GuiDocEditFooter(QWidget):
3051
3010
  self.setContentsMargins(0, 0, 0, 0)
3052
3011
  self.setAutoFillBackground(True)
3053
3012
 
3054
- alLeftTop = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop
3055
-
3056
3013
  # Status
3057
3014
  self.statusIcon = QLabel("", self)
3058
3015
  self.statusIcon.setContentsMargins(0, 0, 0, 0)
3059
3016
  self.statusIcon.setFixedHeight(iPx)
3060
- self.statusIcon.setAlignment(alLeftTop)
3017
+ self.statusIcon.setAlignment(QtAlignLeftTop)
3061
3018
 
3062
- self.statusText = QLabel(self.tr("Status"))
3019
+ self.statusText = QLabel(self.tr("Status"), self)
3063
3020
  self.statusText.setIndent(0)
3064
3021
  self.statusText.setMargin(0)
3065
3022
  self.statusText.setContentsMargins(0, 0, 0, 0)
3066
3023
  self.statusText.setAutoFillBackground(True)
3067
3024
  self.statusText.setFixedHeight(fPx)
3068
- self.statusText.setAlignment(alLeftTop)
3025
+ self.statusText.setAlignment(QtAlignLeftTop)
3069
3026
  self.statusText.setFont(lblFont)
3070
3027
 
3071
3028
  # Lines
3072
3029
  self.linesIcon = QLabel("", self)
3073
3030
  self.linesIcon.setContentsMargins(0, 0, 0, 0)
3074
3031
  self.linesIcon.setFixedHeight(iPx)
3075
- self.linesIcon.setAlignment(alLeftTop)
3032
+ self.linesIcon.setAlignment(QtAlignLeftTop)
3076
3033
 
3077
3034
  self.linesText = QLabel("", self)
3078
3035
  self.linesText.setIndent(0)
@@ -3080,14 +3037,14 @@ class GuiDocEditFooter(QWidget):
3080
3037
  self.linesText.setContentsMargins(0, 0, 0, 0)
3081
3038
  self.linesText.setAutoFillBackground(True)
3082
3039
  self.linesText.setFixedHeight(fPx)
3083
- self.linesText.setAlignment(alLeftTop)
3040
+ self.linesText.setAlignment(QtAlignLeftTop)
3084
3041
  self.linesText.setFont(lblFont)
3085
3042
 
3086
3043
  # Words
3087
3044
  self.wordsIcon = QLabel("", self)
3088
3045
  self.wordsIcon.setContentsMargins(0, 0, 0, 0)
3089
3046
  self.wordsIcon.setFixedHeight(iPx)
3090
- self.wordsIcon.setAlignment(alLeftTop)
3047
+ self.wordsIcon.setAlignment(QtAlignLeftTop)
3091
3048
 
3092
3049
  self.wordsText = QLabel("", self)
3093
3050
  self.wordsText.setIndent(0)
@@ -3095,7 +3052,7 @@ class GuiDocEditFooter(QWidget):
3095
3052
  self.wordsText.setContentsMargins(0, 0, 0, 0)
3096
3053
  self.wordsText.setAutoFillBackground(True)
3097
3054
  self.wordsText.setFixedHeight(fPx)
3098
- self.wordsText.setAlignment(alLeftTop)
3055
+ self.wordsText.setAlignment(QtAlignLeftTop)
3099
3056
  self.wordsText.setFont(lblFont)
3100
3057
 
3101
3058
  # Assemble Layout
@@ -3134,7 +3091,7 @@ class GuiDocEditFooter(QWidget):
3134
3091
 
3135
3092
  def updateTheme(self) -> None:
3136
3093
  """Update theme elements."""
3137
- iPx = round(0.9*SHARED.theme.baseIconSize)
3094
+ iPx = round(0.9*SHARED.theme.baseIconHeight)
3138
3095
  self.linesIcon.setPixmap(SHARED.theme.getPixmap("status_lines", (iPx, iPx)))
3139
3096
  self.wordsIcon.setPixmap(SHARED.theme.getPixmap("status_stats", (iPx, iPx)))
3140
3097
  self.matchColours()
@@ -3176,7 +3133,7 @@ class GuiDocEditFooter(QWidget):
3176
3133
  sIcon = QPixmap()
3177
3134
  sText = ""
3178
3135
  else:
3179
- iPx = round(0.9*SHARED.theme.baseIconSize)
3136
+ iPx = round(0.9*SHARED.theme.baseIconHeight)
3180
3137
  status, icon = self._tItem.getImportStatus(incIcon=True)
3181
3138
  sIcon = icon.pixmap(iPx, iPx)
3182
3139
  sText = f"{status} / {self._tItem.describeMe()}"