novelWriter 2.7.4__py3-none-any.whl → 2.7.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/__init__.py +3 -3
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/manual_fr.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/gui/doceditor.py +49 -22
- novelwriter/types.py +2 -0
- {novelwriter-2.7.4.dist-info → novelwriter-2.7.5.dist-info}/METADATA +1 -1
- {novelwriter-2.7.4.dist-info → novelwriter-2.7.5.dist-info}/RECORD +13 -13
- {novelwriter-2.7.4.dist-info → novelwriter-2.7.5.dist-info}/WHEEL +0 -0
- {novelwriter-2.7.4.dist-info → novelwriter-2.7.5.dist-info}/entry_points.txt +0 -0
- {novelwriter-2.7.4.dist-info → novelwriter-2.7.5.dist-info}/licenses/LICENSE.md +0 -0
- {novelwriter-2.7.4.dist-info → novelwriter-2.7.5.dist-info}/licenses/setup/LICENSE-Apache-2.0.txt +0 -0
- {novelwriter-2.7.4.dist-info → novelwriter-2.7.5.dist-info}/top_level.txt +0 -0
novelwriter/__init__.py
CHANGED
@@ -49,9 +49,9 @@ __license__ = "GPLv3"
|
|
49
49
|
__author__ = "Veronica Berglyd Olsen"
|
50
50
|
__maintainer__ = "Veronica Berglyd Olsen"
|
51
51
|
__email__ = "code@vkbo.net"
|
52
|
-
__version__ = "2.7.
|
53
|
-
__hexversion__ = "
|
54
|
-
__date__ = "2025-
|
52
|
+
__version__ = "2.7.5"
|
53
|
+
__hexversion__ = "0x020705f0"
|
54
|
+
__date__ = "2025-09-14"
|
55
55
|
__status__ = "Stable"
|
56
56
|
__domain__ = "novelwriter.io"
|
57
57
|
|
novelwriter/assets/manual.pdf
CHANGED
Binary file
|
novelwriter/assets/manual_fr.pdf
CHANGED
Binary file
|
novelwriter/assets/sample.zip
CHANGED
Binary file
|
novelwriter/gui/doceditor.py
CHANGED
@@ -39,13 +39,14 @@ from enum import Enum, IntFlag
|
|
39
39
|
from time import time
|
40
40
|
|
41
41
|
from PyQt6.QtCore import (
|
42
|
-
QObject, QPoint, QRegularExpression, QRunnable, Qt, QTimer,
|
43
|
-
pyqtSlot
|
42
|
+
QObject, QPoint, QRect, QRegularExpression, QRunnable, Qt, QTimer,
|
43
|
+
QVariant, pyqtSignal, pyqtSlot
|
44
44
|
)
|
45
45
|
from PyQt6.QtGui import (
|
46
|
-
QAction, QCursor, QDragEnterEvent, QDragMoveEvent, QDropEvent,
|
47
|
-
QKeySequence, QMouseEvent, QPalette, QPixmap,
|
48
|
-
QTextBlock, QTextCursor, QTextDocument,
|
46
|
+
QAction, QCursor, QDragEnterEvent, QDragMoveEvent, QDropEvent,
|
47
|
+
QInputMethodEvent, QKeyEvent, QKeySequence, QMouseEvent, QPalette, QPixmap,
|
48
|
+
QResizeEvent, QShortcut, QTextBlock, QTextCursor, QTextDocument,
|
49
|
+
QTextOption
|
49
50
|
)
|
50
51
|
from PyQt6.QtWidgets import (
|
51
52
|
QApplication, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu,
|
@@ -74,8 +75,9 @@ from novelwriter.text.counting import standardCounter
|
|
74
75
|
from novelwriter.tools.lipsum import GuiLipsum
|
75
76
|
from novelwriter.types import (
|
76
77
|
QtAlignCenterTop, QtAlignJustify, QtAlignLeft, QtAlignLeftTop,
|
77
|
-
QtAlignRight, QtKeepAnchor, QtModCtrl, QtModNone,
|
78
|
-
QtMoveAnchor, QtMoveLeft, QtMoveRight,
|
78
|
+
QtAlignRight, QtImCursorRectangle, QtKeepAnchor, QtModCtrl, QtModNone,
|
79
|
+
QtModShift, QtMouseLeft, QtMoveAnchor, QtMoveLeft, QtMoveRight,
|
80
|
+
QtScrollAlwaysOff, QtScrollAsNeeded
|
79
81
|
)
|
80
82
|
|
81
83
|
logger = logging.getLogger(__name__)
|
@@ -151,7 +153,7 @@ class GuiDocEditor(QPlainTextEdit):
|
|
151
153
|
|
152
154
|
# Completer
|
153
155
|
self._completer = CommandCompleter(self)
|
154
|
-
self._completer.
|
156
|
+
self._completer.insertText.connect(self._insertCompletion)
|
155
157
|
|
156
158
|
# Create Custom Document
|
157
159
|
self._qDocument = GuiTextDocument(self)
|
@@ -914,7 +916,7 @@ class GuiDocEditor(QPlainTextEdit):
|
|
914
916
|
return True
|
915
917
|
|
916
918
|
##
|
917
|
-
#
|
919
|
+
# Events and Overloads
|
918
920
|
##
|
919
921
|
|
920
922
|
def keyPressEvent(self, event: QKeyEvent) -> None:
|
@@ -1017,6 +1019,26 @@ class GuiDocEditor(QPlainTextEdit):
|
|
1017
1019
|
super().resizeEvent(event)
|
1018
1020
|
return
|
1019
1021
|
|
1022
|
+
def inputMethodEvent(self, event: QInputMethodEvent) -> None:
|
1023
|
+
"""Handle text being input from CJK input methods."""
|
1024
|
+
super().inputMethodEvent(event)
|
1025
|
+
if event.commitString():
|
1026
|
+
# See issues #2267 and #2517
|
1027
|
+
self.ensureCursorVisible()
|
1028
|
+
self._completerToCursor()
|
1029
|
+
|
1030
|
+
def inputMethodQuery(self, query: Qt.InputMethodQuery) -> QRect | QVariant:
|
1031
|
+
"""Adjust completion windows for CJK input methods to consider
|
1032
|
+
the viewport margins.
|
1033
|
+
"""
|
1034
|
+
if query == QtImCursorRectangle:
|
1035
|
+
# See issues #2267 and #2517
|
1036
|
+
vM = self.viewportMargins()
|
1037
|
+
rect = self.cursorRect()
|
1038
|
+
rect.translate(vM.left(), vM.top())
|
1039
|
+
return rect
|
1040
|
+
return super().inputMethodQuery(query)
|
1041
|
+
|
1020
1042
|
##
|
1021
1043
|
# Public Slots
|
1022
1044
|
##
|
@@ -1080,24 +1102,20 @@ class GuiDocEditor(QPlainTextEdit):
|
|
1080
1102
|
|
1081
1103
|
if (block := self._qDocument.findBlock(pos)).isValid():
|
1082
1104
|
text = block.text()
|
1105
|
+
|
1083
1106
|
if text and text[0] in "@%" and added + removed == 1:
|
1084
1107
|
# Only run on single character changes, or it will trigger
|
1085
1108
|
# at unwanted times when other changes are made to the document
|
1086
1109
|
cursor = self.textCursor()
|
1087
1110
|
bPos = cursor.positionInBlock()
|
1088
|
-
if bPos > 0
|
1111
|
+
if bPos > 0:
|
1089
1112
|
if text[0] == "@":
|
1090
1113
|
show = self._completer.updateMetaText(text, bPos)
|
1091
1114
|
else:
|
1092
1115
|
show = self._completer.updateCommentText(text, bPos)
|
1093
1116
|
if show:
|
1094
|
-
point = self.cursorRect().bottomRight()
|
1095
|
-
self._completer.move(viewport.mapToGlobal(point))
|
1096
1117
|
self._completer.show()
|
1097
|
-
|
1098
|
-
self._completer.close()
|
1099
|
-
else:
|
1100
|
-
self._completer.close()
|
1118
|
+
self._completerToCursor()
|
1101
1119
|
|
1102
1120
|
if self._doReplace and added == 1:
|
1103
1121
|
cursor = self.textCursor()
|
@@ -1121,7 +1139,7 @@ class GuiDocEditor(QPlainTextEdit):
|
|
1121
1139
|
cursor.setPosition(check, QtMoveAnchor)
|
1122
1140
|
cursor.setPosition(check + length, QtKeepAnchor)
|
1123
1141
|
cursor.insertText(text)
|
1124
|
-
self._completer.
|
1142
|
+
self._completer.close()
|
1125
1143
|
return
|
1126
1144
|
|
1127
1145
|
@pyqtSlot()
|
@@ -1898,6 +1916,12 @@ class GuiDocEditor(QPlainTextEdit):
|
|
1898
1916
|
# Internal Functions
|
1899
1917
|
##
|
1900
1918
|
|
1919
|
+
def _completerToCursor(self) -> None:
|
1920
|
+
"""Make sure the completer menu is positioned by the cursor."""
|
1921
|
+
if self._completer.isVisible() and (viewport := self.viewport()):
|
1922
|
+
point = self.cursorRect().bottomLeft()
|
1923
|
+
self._completer.move(viewport.mapToGlobal(point))
|
1924
|
+
|
1901
1925
|
def _correctWord(self, cursor: QTextCursor, word: str) -> None:
|
1902
1926
|
"""Slot for the spell check context menu triggering the
|
1903
1927
|
replacement of a word with the word from the dictionary.
|
@@ -2089,10 +2113,13 @@ class CommandCompleter(QMenu):
|
|
2089
2113
|
called on every keystroke on a line starting with @ or %.
|
2090
2114
|
"""
|
2091
2115
|
|
2092
|
-
|
2116
|
+
__slots__ = ("_parent",)
|
2117
|
+
|
2118
|
+
insertText = pyqtSignal(int, int, str)
|
2093
2119
|
|
2094
2120
|
def __init__(self, parent: QWidget) -> None:
|
2095
2121
|
super().__init__(parent=parent)
|
2122
|
+
self._parent = parent
|
2096
2123
|
return
|
2097
2124
|
|
2098
2125
|
def updateMetaText(self, text: str, pos: int) -> bool:
|
@@ -2179,14 +2206,14 @@ class CommandCompleter(QMenu):
|
|
2179
2206
|
|
2180
2207
|
def keyPressEvent(self, event: QKeyEvent) -> None:
|
2181
2208
|
"""Capture keypresses and forward most of them to the editor."""
|
2182
|
-
parent = self.parent()
|
2183
2209
|
if event.key() in (
|
2184
2210
|
Qt.Key.Key_Up, Qt.Key.Key_Down, Qt.Key.Key_Return,
|
2185
2211
|
Qt.Key.Key_Enter, Qt.Key.Key_Escape
|
2186
2212
|
):
|
2187
2213
|
super().keyPressEvent(event)
|
2188
|
-
|
2189
|
-
|
2214
|
+
else:
|
2215
|
+
self.close() # Close to release the event lock before forwarding the key press (#2510)
|
2216
|
+
self._parent.keyPressEvent(event)
|
2190
2217
|
return
|
2191
2218
|
|
2192
2219
|
##
|
@@ -2195,7 +2222,7 @@ class CommandCompleter(QMenu):
|
|
2195
2222
|
|
2196
2223
|
def _emitComplete(self, pos: int, length: int, value: str) -> None:
|
2197
2224
|
"""Emit the signal to indicate a selection has been made."""
|
2198
|
-
self.
|
2225
|
+
self.insertText.emit(pos, length, value)
|
2199
2226
|
return
|
2200
2227
|
|
2201
2228
|
|
novelwriter/types.py
CHANGED
@@ -110,6 +110,8 @@ QtMoveAnchor = QTextCursor.MoveMode.MoveAnchor
|
|
110
110
|
QtMoveLeft = QTextCursor.MoveOperation.Left
|
111
111
|
QtMoveRight = QTextCursor.MoveOperation.Right
|
112
112
|
|
113
|
+
QtImCursorRectangle = Qt.InputMethodQuery.ImCursorRectangle
|
114
|
+
|
113
115
|
# Size Policy
|
114
116
|
|
115
117
|
QtSizeExpanding = QSizePolicy.Policy.Expanding
|
@@ -1,4 +1,4 @@
|
|
1
|
-
novelwriter/__init__.py,sha256=
|
1
|
+
novelwriter/__init__.py,sha256=i2yxxsiWOaTaLa7RQR3_sBc0eoCLEELdw_0wTkAeBmg,9566
|
2
2
|
novelwriter/common.py,sha256=J4WNfcXWdeImTPhkY1vuWoVEQWTpIUE6t7Hwd3GiVzk,22243
|
3
3
|
novelwriter/config.py,sha256=PXzcruFnFuqS4zH9RJ0hf0oUs9Vndo-i6aPOBzadsp0,44643
|
4
4
|
novelwriter/constants.py,sha256=j_Z3cb-_wW7_cxzTdoRVR9JvmYbioLAp8Dh9TluFJSQ,28827
|
@@ -7,10 +7,10 @@ novelwriter/error.py,sha256=HPKDJb0NPTyVRsrPNG_I1-XfLXlvYAJuE2Xi7maWvXM,6828
|
|
7
7
|
novelwriter/guimain.py,sha256=luIw3434s92wEuU4gKkerp0MQGtD_hDlCVY6ioZu0LQ,50293
|
8
8
|
novelwriter/shared.py,sha256=8JTkFi7QXmQddGNVaSBIvKPfDXLaJ9XWNmUJblpfXvs,17795
|
9
9
|
novelwriter/splash.py,sha256=rK71vO7NG2NETTf1vvQiWRHfkHonf2Z0xhLj_LF_wj8,2237
|
10
|
-
novelwriter/types.py,sha256=
|
11
|
-
novelwriter/assets/manual.pdf,sha256=
|
12
|
-
novelwriter/assets/manual_fr.pdf,sha256=
|
13
|
-
novelwriter/assets/sample.zip,sha256=
|
10
|
+
novelwriter/types.py,sha256=7RhAne83H04evhuN72KlI-O3hq-9gqsgbD2zhEgQcss,5231
|
11
|
+
novelwriter/assets/manual.pdf,sha256=nnkuryQvo3Ms22ZCUk2aGv1cZbeRqdX3-JXEgkUfScI,2131017
|
12
|
+
novelwriter/assets/manual_fr.pdf,sha256=c_gXVB6HLe7YTf-trOH6RYWVE3L8H7BMHjZAdYeQBGs,2190065
|
13
|
+
novelwriter/assets/sample.zip,sha256=wr0MuFIEMt_zEaOGUkEPAWrkutLuRUfH5HyBE0E-e7A,13982
|
14
14
|
novelwriter/assets/i18n/nw_cs_CZ.qm,sha256=Y86wuWVB0yQBL6F5P6l-W61isSGJEkCanPa_S5eTYFc,100334
|
15
15
|
novelwriter/assets/i18n/nw_de_DE.qm,sha256=VwyhNBVst94jlAsdsyUbzj4_ucGX6QLp16wve2jlCjg,105152
|
16
16
|
novelwriter/assets/i18n/nw_en_US.qm,sha256=rK_f6bhwlzqLygB9xfQr9mPLDZAPmutYHr3vie-Kf5k,98000
|
@@ -129,7 +129,7 @@ novelwriter/formats/tomarkdown.py,sha256=CN9mJRwqoit1c9rOHwsqBZEpPjEWYvh81IVgttU
|
|
129
129
|
novelwriter/formats/toodt.py,sha256=LuzN8vE46mclcfpOs9QZcElXDVOx14wjyKPkOQE6KYQ,58672
|
130
130
|
novelwriter/formats/toqdoc.py,sha256=aJGFhq482p7lxr72bCidd2KkpkNH0mcsQvV2AcI1zgo,18315
|
131
131
|
novelwriter/formats/toraw.py,sha256=6qLNvDc87t6c25j1H2IL9whajp1u-SOnHFk9c4gV_7E,2903
|
132
|
-
novelwriter/gui/doceditor.py,sha256=
|
132
|
+
novelwriter/gui/doceditor.py,sha256=lcOo2AUcuLGTxLFLur2qw45vQbKxdSvLWB9lCtXoTUI,118545
|
133
133
|
novelwriter/gui/dochighlight.py,sha256=DDCEK9iKUBd5miScrJCj9NlRj3sdOgD_bY8_4ARsSMg,19576
|
134
134
|
novelwriter/gui/docviewer.py,sha256=7r24roJ1NcGAXC022Yo3wqdwb3AgpCkX65vN7xxQja8,34569
|
135
135
|
novelwriter/gui/docviewerpanel.py,sha256=m5e9hO5dgV729RnOEJzNzCOU2CB3vPzp4TB4HKgTjGA,19361
|
@@ -154,10 +154,10 @@ novelwriter/tools/manussettings.py,sha256=pQhugOCzL957M7pqT2szajZzNgnWWA1qFiIHex
|
|
154
154
|
novelwriter/tools/noveldetails.py,sha256=4BVi3Pc6HNJlYcYnyHKiIuR23uKZ9elNZOcJJOoLlAw,18067
|
155
155
|
novelwriter/tools/welcome.py,sha256=f657EWmQxe3l2sRL3Wq1A9R5mnFciivAF5TDbsUlsRc,27431
|
156
156
|
novelwriter/tools/writingstats.py,sha256=3U4dUlaeNR16E_Kxo5am8ov3ICH0j6S48FLJ-IptHDI,23161
|
157
|
-
novelwriter-2.7.
|
158
|
-
novelwriter-2.7.
|
159
|
-
novelwriter-2.7.
|
160
|
-
novelwriter-2.7.
|
161
|
-
novelwriter-2.7.
|
162
|
-
novelwriter-2.7.
|
163
|
-
novelwriter-2.7.
|
157
|
+
novelwriter-2.7.5.dist-info/licenses/LICENSE.md,sha256=2GirkkLrPfQqx7fACKRJjtKJUegKc8067erGvcDVQHM,32197
|
158
|
+
novelwriter-2.7.5.dist-info/licenses/setup/LICENSE-Apache-2.0.txt,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
159
|
+
novelwriter-2.7.5.dist-info/METADATA,sha256=Xv_w4ptsO-vn-OQR6U6PxtrwTuHpANlXhtsvgptk3PE,2539
|
160
|
+
novelwriter-2.7.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
161
|
+
novelwriter-2.7.5.dist-info/entry_points.txt,sha256=YDUG1w361LtLsjD3YhxoTDTwM17JA5-nigjC6j5C74A,45
|
162
|
+
novelwriter-2.7.5.dist-info/top_level.txt,sha256=wFFEucjEeNC_Ap5ULBuEutg5a1Uc0-YO9uFT5L2naNI,12
|
163
|
+
novelwriter-2.7.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
{novelwriter-2.7.4.dist-info → novelwriter-2.7.5.dist-info}/licenses/setup/LICENSE-Apache-2.0.txt
RENAMED
File without changes
|
File without changes
|