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