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.
- {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/METADATA +5 -6
- {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/RECORD +62 -66
- novelwriter/__init__.py +5 -5
- novelwriter/assets/icons/none.svg +4 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +2 -2
- novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +2 -2
- novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/common.py +6 -1
- novelwriter/config.py +8 -4
- novelwriter/core/coretools.py +21 -22
- novelwriter/core/status.py +3 -2
- novelwriter/core/toodt.py +332 -355
- novelwriter/dialogs/about.py +9 -11
- novelwriter/dialogs/docmerge.py +17 -14
- novelwriter/dialogs/docsplit.py +14 -12
- novelwriter/dialogs/editlabel.py +5 -4
- novelwriter/dialogs/preferences.py +28 -33
- novelwriter/dialogs/projectsettings.py +29 -26
- novelwriter/dialogs/quotes.py +10 -9
- novelwriter/dialogs/wordlist.py +15 -12
- novelwriter/error.py +13 -11
- novelwriter/extensions/circularprogress.py +12 -8
- novelwriter/extensions/configlayout.py +1 -3
- novelwriter/extensions/modified.py +33 -2
- novelwriter/extensions/pagedsidebar.py +16 -14
- novelwriter/extensions/simpleprogress.py +3 -1
- novelwriter/extensions/statusled.py +3 -1
- novelwriter/extensions/switch.py +10 -9
- novelwriter/extensions/switchbox.py +14 -13
- novelwriter/gui/doceditor.py +182 -225
- novelwriter/gui/dochighlight.py +4 -4
- novelwriter/gui/docviewer.py +53 -57
- novelwriter/gui/docviewerpanel.py +16 -13
- novelwriter/gui/editordocument.py +4 -4
- novelwriter/gui/itemdetails.py +45 -48
- novelwriter/gui/noveltree.py +22 -20
- novelwriter/gui/outline.py +87 -88
- novelwriter/gui/projtree.py +31 -29
- novelwriter/gui/search.py +75 -29
- novelwriter/gui/sidebar.py +24 -28
- novelwriter/gui/statusbar.py +14 -14
- novelwriter/gui/theme.py +47 -35
- novelwriter/guimain.py +35 -31
- novelwriter/shared.py +5 -5
- novelwriter/tools/dictionaries.py +13 -12
- novelwriter/tools/lipsum.py +20 -17
- novelwriter/tools/manusbuild.py +35 -27
- novelwriter/tools/manuscript.py +68 -73
- novelwriter/tools/manussettings.py +68 -73
- novelwriter/tools/noveldetails.py +20 -18
- novelwriter/tools/welcome.py +47 -43
- novelwriter/tools/writingstats.py +61 -55
- novelwriter/types.py +90 -0
- novelwriter/assets/icons/typicons_dark/typ_arrow-down.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_arrow-right.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_arrow-down.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_arrow-right.svg +0 -4
- novelwriter/core/__init__.py +0 -3
- novelwriter/dialogs/__init__.py +0 -3
- novelwriter/extensions/__init__.py +0 -3
- novelwriter/gui/__init__.py +0 -3
- novelwriter/text/__init__.py +0 -3
- novelwriter/tools/__init__.py +0 -3
- {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/WHEEL +0 -0
- {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/top_level.txt +0 -0
novelwriter/gui/doceditor.py
CHANGED
@@ -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,
|
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,
|
51
|
-
|
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 |
|
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 |
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
432
|
+
QApplication.processEvents()
|
424
433
|
self.setDocumentChanged(False)
|
425
434
|
self._qDocument.clearUndoRedoStacks()
|
426
435
|
self.docToolBar.setVisible(CONFIG.showEditToolBar)
|
427
436
|
|
428
|
-
|
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
|
-
|
454
|
+
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
446
455
|
self.setPlainText(text)
|
447
456
|
self.updateDocMargins()
|
448
457
|
self.setDocumentChanged(True)
|
449
|
-
|
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
|
-
|
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,
|
660
|
+
def setCursorSelection(self, start: int, length: int) -> None:
|
643
661
|
"""Make a text selection."""
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
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
|
-
|
708
|
+
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
690
709
|
self._qDocument.syntaxHighlighter.rehighlight()
|
691
|
-
|
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(
|
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 (
|
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(
|
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
|
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.
|
1025
|
-
self.
|
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,
|
1082
|
-
cursor.setPosition(pos + length,
|
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.
|
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
|
1202
|
-
|
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
|
-
|
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
|
1321
|
+
if CONFIG.searchNextFile and not goBack:
|
1313
1322
|
self.mainGui.openNextDocument(
|
1314
|
-
self._docHandle, wrapAround=
|
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 =
|
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
|
1342
|
+
if CONFIG.searchNextFile and not goBack:
|
1334
1343
|
self.mainGui.openNextDocument(
|
1335
|
-
self._docHandle, wrapAround=
|
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],
|
1344
|
-
cursor.setPosition(resE[resIdx],
|
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
|
1377
|
+
if CONFIG.searchCase:
|
1369
1378
|
findOpt |= QTextDocument.FindFlag.FindCaseSensitively
|
1370
|
-
if
|
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,
|
1391
|
-
cursor.setPosition(origB,
|
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
|
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,
|
1495
|
-
cursor.setPosition(posE,
|
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),
|
1573
|
-
cursor.setPosition(posS + len(before),
|
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
|
-
|
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,
|
2069
|
-
cursor.setPosition(ePos,
|
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,
|
2094
|
-
cursor.setPosition(posE,
|
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.
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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.
|
2376
|
-
self.tbItalicMD.
|
2377
|
-
self.tbStrikeMD.
|
2378
|
-
self.tbBold.
|
2379
|
-
self.tbItalic.
|
2380
|
-
self.tbStrike.
|
2381
|
-
self.tbUnderline.
|
2382
|
-
self.tbMark.
|
2383
|
-
self.tbSuperscript.
|
2384
|
-
self.tbSubscript.
|
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
|
-
|
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
|
-
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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.
|
2473
|
+
self.cancelSearch.triggered.connect(self.closeSearch)
|
2493
2474
|
self.searchOpt.addAction(self.cancelSearch)
|
2494
2475
|
|
2495
2476
|
# Buttons
|
2496
2477
|
# =======
|
2497
2478
|
|
2498
|
-
|
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 =
|
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 =
|
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,
|
2516
|
-
self.mainBox.addWidget(self.searchOpt, 0, 2, 1, 3,
|
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
|
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
|
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
|
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
|
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 =
|
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.
|
2650
|
-
self.replaceButton.
|
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
|
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.
|
2697
|
-
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
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()
|
2665
|
+
return self.searchBox.hasFocus() or self.replaceBox.hasFocus()
|
2708
2666
|
|
2709
2667
|
##
|
2710
|
-
#
|
2668
|
+
# Public Slots
|
2711
2669
|
##
|
2712
2670
|
|
2713
2671
|
@pyqtSlot()
|
2714
|
-
def
|
2715
|
-
"""
|
2716
|
-
self.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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(
|
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,
|
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,
|
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,
|
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,
|
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,
|
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.
|
2932
|
-
self.outlineButton.
|
2933
|
-
self.searchButton.
|
2934
|
-
self.minmaxButton.
|
2935
|
-
self.closeButton.
|
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.
|
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() ==
|
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.
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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.
|
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.
|
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()}"
|