Skip to content

Commit 6ed29cf

Browse files
authored
Adjust windows for IME conversion suggestions to not cover text (#2518)
2 parents 3be8eb4 + da6b9b0 commit 6ed29cf

File tree

3 files changed

+55
-12
lines changed

3 files changed

+55
-12
lines changed

novelwriter/gui/doceditor.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@
3939
from time import time
4040

4141
from PyQt6.QtCore import (
42-
QObject, QPoint, QRegularExpression, QRunnable, Qt, QTimer, pyqtSignal,
43-
pyqtSlot
42+
QObject, QPoint, QRect, QRegularExpression, QRunnable, Qt, QTimer,
43+
QVariant, pyqtSignal, pyqtSlot
4444
)
4545
from PyQt6.QtGui import (
46-
QAction, QCursor, QDragEnterEvent, QDragMoveEvent, QDropEvent, QKeyEvent,
47-
QKeySequence, QMouseEvent, QPalette, QPixmap, QResizeEvent, QShortcut,
48-
QTextBlock, QTextCursor, QTextDocument, QTextOption
46+
QAction, QCursor, QDragEnterEvent, QDragMoveEvent, QDropEvent,
47+
QInputMethodEvent, QKeyEvent, QKeySequence, QMouseEvent, QPalette, QPixmap,
48+
QResizeEvent, QShortcut, QTextBlock, QTextCursor, QTextDocument,
49+
QTextOption
4950
)
5051
from PyQt6.QtWidgets import (
5152
QApplication, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu,
@@ -74,8 +75,9 @@
7475
from novelwriter.tools.lipsum import GuiLipsum
7576
from novelwriter.types import (
7677
QtAlignCenterTop, QtAlignJustify, QtAlignLeft, QtAlignLeftTop,
77-
QtAlignRight, QtKeepAnchor, QtModCtrl, QtModNone, QtModShift, QtMouseLeft,
78-
QtMoveAnchor, QtMoveLeft, QtMoveRight, QtScrollAlwaysOff, QtScrollAsNeeded
78+
QtAlignRight, QtImCursorRectangle, QtKeepAnchor, QtModCtrl, QtModNone,
79+
QtModShift, QtMouseLeft, QtMoveAnchor, QtMoveLeft, QtMoveRight,
80+
QtScrollAlwaysOff, QtScrollAsNeeded
7981
)
8082

8183
logger = logging.getLogger(__name__)
@@ -914,7 +916,7 @@ def insertNewBlock(self, text: str, defaultAfter: bool = True) -> bool:
914916
return True
915917

916918
##
917-
# Document Events and Maintenance
919+
# Events and Overloads
918920
##
919921

920922
def keyPressEvent(self, event: QKeyEvent) -> None:
@@ -1017,6 +1019,26 @@ def resizeEvent(self, event: QResizeEvent) -> None:
10171019
super().resizeEvent(event)
10181020
return
10191021

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+
10201042
##
10211043
# Public Slots
10221044
##
@@ -1086,15 +1108,14 @@ def _docChange(self, pos: int, removed: int, added: int) -> None:
10861108
# at unwanted times when other changes are made to the document
10871109
cursor = self.textCursor()
10881110
bPos = cursor.positionInBlock()
1089-
if bPos > 0 and (viewport := self.viewport()):
1111+
if bPos > 0:
10901112
if text[0] == "@":
10911113
show = self._completer.updateMetaText(text, bPos)
10921114
else:
10931115
show = self._completer.updateCommentText(text, bPos)
10941116
if show:
1095-
point = self.cursorRect().bottomRight()
1096-
self._completer.move(viewport.mapToGlobal(point))
10971117
self._completer.show()
1118+
self._completerToCursor()
10981119

10991120
if self._doReplace and added == 1:
11001121
cursor = self.textCursor()
@@ -1895,6 +1916,12 @@ def _insertCommentStructure(self, style: nwComment) -> None:
18951916
# Internal Functions
18961917
##
18971918

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+
18981925
def _correctWord(self, cursor: QTextCursor, word: str) -> None:
18991926
"""Slot for the spell check context menu triggering the
19001927
replacement of a word with the word from the dictionary.

novelwriter/types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@
110110
QtMoveLeft = QTextCursor.MoveOperation.Left
111111
QtMoveRight = QTextCursor.MoveOperation.Right
112112

113+
QtImCursorRectangle = Qt.InputMethodQuery.ImCursorRectangle
114+
113115
# Size Policy
114116

115117
QtSizeExpanding = QSizePolicy.Policy.Expanding

tests/test_gui/test_gui_doceditor.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
from PyQt6.QtCore import QEvent, QMimeData, QPointF, Qt, QThreadPool, QUrl
2828
from PyQt6.QtGui import (
2929
QAction, QClipboard, QDesktopServices, QDragEnterEvent, QDragMoveEvent,
30-
QDropEvent, QFont, QMouseEvent, QTextBlock, QTextCursor, QTextOption
30+
QDropEvent, QFont, QInputMethodEvent, QMouseEvent, QTextBlock, QTextCursor,
31+
QTextOption
3132
)
3233
from PyQt6.QtWidgets import QApplication, QMenu, QPlainTextEdit
3334

@@ -1941,6 +1942,19 @@ def testGuiEditor_Completer(qtbot, nwGUI, projPath, mockRnd):
19411942
"%Note.Consistency: \n"
19421943
)
19431944

1945+
# CJK completer reposition (#2267 and #2517)
1946+
qtbot.keyClick(docEditor, "%", delay=KEY_DELAY)
1947+
assert completer.isVisible() is True
1948+
completer.move(0, 0)
1949+
assert completer.pos().x() == 0 # Completer menu at 0
1950+
assert completer.pos().y() == 0 # Completer menu at 0
1951+
1952+
event = QInputMethodEvent()
1953+
event.setCommitString("Text")
1954+
docEditor.inputMethodEvent(event)
1955+
assert completer.pos().x() > 0 # Completer should have moved
1956+
assert completer.pos().y() > 0 # Completer should have moved
1957+
19441958
# qtbot.stop()
19451959

19461960

0 commit comments

Comments
 (0)