Fix auto complete crash (#2511)

This commit is contained in:
Veronica Berglyd Olsen
2025-08-31 15:35:57 +02:00
committed by GitHub
3 changed files with 17 additions and 17 deletions
+11 -11
View File
@@ -151,7 +151,7 @@ class GuiDocEditor(QPlainTextEdit):
# Completer # Completer
self._completer = CommandCompleter(self) self._completer = CommandCompleter(self)
self._completer.complete.connect(self._insertCompletion) self._completer.insertText.connect(self._insertCompletion)
# Create Custom Document # Create Custom Document
self._qDocument = GuiTextDocument(self) self._qDocument = GuiTextDocument(self)
@@ -1080,6 +1080,7 @@ class GuiDocEditor(QPlainTextEdit):
if (block := self._qDocument.findBlock(pos)).isValid(): if (block := self._qDocument.findBlock(pos)).isValid():
text = block.text() text = block.text()
if text and text[0] in "@%" and added + removed == 1: if text and text[0] in "@%" and added + removed == 1:
# Only run on single character changes, or it will trigger # Only run on single character changes, or it will trigger
# at unwanted times when other changes are made to the document # at unwanted times when other changes are made to the document
@@ -1094,10 +1095,6 @@ class GuiDocEditor(QPlainTextEdit):
point = self.cursorRect().bottomRight() point = self.cursorRect().bottomRight()
self._completer.move(viewport.mapToGlobal(point)) self._completer.move(viewport.mapToGlobal(point))
self._completer.show() self._completer.show()
else:
self._completer.close()
else:
self._completer.close()
if self._doReplace and added == 1: if self._doReplace and added == 1:
cursor = self.textCursor() cursor = self.textCursor()
@@ -1121,7 +1118,7 @@ class GuiDocEditor(QPlainTextEdit):
cursor.setPosition(check, QtMoveAnchor) cursor.setPosition(check, QtMoveAnchor)
cursor.setPosition(check + length, QtKeepAnchor) cursor.setPosition(check + length, QtKeepAnchor)
cursor.insertText(text) cursor.insertText(text)
self._completer.hide() self._completer.close()
return return
@pyqtSlot() @pyqtSlot()
@@ -2089,10 +2086,13 @@ class CommandCompleter(QMenu):
called on every keystroke on a line starting with @ or %. called on every keystroke on a line starting with @ or %.
""" """
complete = pyqtSignal(int, int, str) __slots__ = ("_parent",)
insertText = pyqtSignal(int, int, str)
def __init__(self, parent: QWidget) -> None: def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
self._parent = parent
return return
def updateMetaText(self, text: str, pos: int) -> bool: def updateMetaText(self, text: str, pos: int) -> bool:
@@ -2179,14 +2179,14 @@ class CommandCompleter(QMenu):
def keyPressEvent(self, event: QKeyEvent) -> None: def keyPressEvent(self, event: QKeyEvent) -> None:
"""Capture keypresses and forward most of them to the editor.""" """Capture keypresses and forward most of them to the editor."""
parent = self.parent()
if event.key() in ( if event.key() in (
Qt.Key.Key_Up, Qt.Key.Key_Down, Qt.Key.Key_Return, Qt.Key.Key_Up, Qt.Key.Key_Down, Qt.Key.Key_Return,
Qt.Key.Key_Enter, Qt.Key.Key_Escape Qt.Key.Key_Enter, Qt.Key.Key_Escape
): ):
super().keyPressEvent(event) super().keyPressEvent(event)
elif isinstance(parent, GuiDocEditor): else:
parent.keyPressEvent(event) self.close() # Close to release the event lock before forwarding the key press (#2510)
self._parent.keyPressEvent(event)
return return
## ##
@@ -2195,7 +2195,7 @@ class CommandCompleter(QMenu):
def _emitComplete(self, pos: int, length: int, value: str) -> None: def _emitComplete(self, pos: int, length: int, value: str) -> None:
"""Emit the signal to indicate a selection has been made.""" """Emit the signal to indicate a selection has been made."""
self.complete.emit(pos, length, value) self.insertText.emit(pos, length, value)
return return
+4 -4
View File
@@ -812,13 +812,13 @@ def testGuiMain_OpenClose(qtbot, monkeypatch, nwGUI, projPath, fncPath, mockRnd)
# Handle broken index on project open # Handle broken index on project open
nwGUI.closeProject() nwGUI.closeProject()
idxPath: Path = projPath / "meta" / nwFiles.INDEX_FILE idxPath: Path = projPath / "meta" / nwFiles.INDEX_FILE
assert idxPath.read_text() != "{}" assert idxPath.read_text(encoding="utf-8") != "{}"
idxPath.write_text("{}") idxPath.write_text("{}", encoding="utf-8")
assert idxPath.read_text() == "{}" assert idxPath.read_text(encoding="utf-8") == "{}"
nwGUI.openProject(projPath) nwGUI.openProject(projPath)
nwGUI.saveProject() nwGUI.saveProject()
assert idxPath.read_text() != "{}" assert idxPath.read_text(encoding="utf-8") != "{}"
assert nwGUI.docEditor.docHandle == C.hSceneDoc assert nwGUI.docEditor.docHandle == C.hSceneDoc
assert nwGUI.docViewer.docHandle == C.hTitlePage assert nwGUI.docViewer.docHandle == C.hTitlePage
+2 -2
View File
@@ -164,14 +164,14 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, tstPaths):
# =============== # ===============
mockTheme: Path = tstPaths.cnfDir / "themes" / "test.conf" mockTheme: Path = tstPaths.cnfDir / "themes" / "test.conf"
mockTheme.write_text( mockTheme.write_text((
"[Main]\n" "[Main]\n"
"name = Test\n" "name = Test\n"
"\n" "\n"
"[Palette]\n" "[Palette]\n"
"window = 0, 0, 0\n" "window = 0, 0, 0\n"
"text = 255, 255, 255\n" "text = 255, 255, 255\n"
) ), encoding="utf-8")
mainTheme._availThemes["test"] = mockTheme mainTheme._availThemes["test"] = mockTheme
CONFIG.guiTheme = "test" CONFIG.guiTheme = "test"