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