Skip to content

Commit c72b2d5

Browse files
committed
Improve handling of completer selection
1 parent d1194a3 commit c72b2d5

1 file changed

Lines changed: 23 additions & 6 deletions

File tree

novelwriter/gui/doceditor.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
from enum import Enum, IntFlag
4040
from time import time
41+
from typing import NamedTuple
4142

4243
from PyQt6 import sip
4344
from PyQt6.QtCore import (
@@ -2536,6 +2537,14 @@ def _skipToParagraph(self, step: int) -> None:
25362537
break
25372538

25382539

2540+
class CompleterAction(NamedTuple):
2541+
"""Values needed to complete a completer action."""
2542+
2543+
pos: int
2544+
length: int
2545+
value: str
2546+
2547+
25392548
class CommandCompleter(QMenu):
25402549
"""GuiWidget: Command Completer Menu.
25412550
@@ -2552,6 +2561,7 @@ class CommandCompleter(QMenu):
25522561
def __init__(self, parent: QWidget) -> None:
25532562
super().__init__(parent=parent)
25542563
self._parent = parent
2564+
self.triggered.connect(self._emitComplete)
25552565

25562566
def updateMetaText(self, text: str, pos: int) -> bool:
25572567
"""Update the menu options based on the line of text."""
@@ -2583,7 +2593,7 @@ def updateMetaText(self, text: str, pos: int) -> bool:
25832593
for value in options:
25842594
rep = value + suffix
25852595
action = qtAddAction(self, value)
2586-
action.triggered.connect(qtLambda(self._emitComplete, offset, length, rep))
2596+
action.setData(CompleterAction(pos=offset, length=length, value=rep))
25872597

25882598
return True
25892599

@@ -2626,7 +2636,7 @@ def updateCommentText(self, text: str, pos: int) -> bool:
26262636
for value in options:
26272637
rep = value + suffix
26282638
action = qtAddAction(self, rep.rstrip(":. "))
2629-
action.triggered.connect(qtLambda(self._emitComplete, offset, length, rep))
2639+
action.setData(CompleterAction(pos=offset, length=length, value=rep))
26302640
return True
26312641

26322642
return False
@@ -2639,28 +2649,35 @@ def keyPressEvent(self, event: QKeyEvent) -> None:
26392649
"""Capture keypresses and forward most of them to the editor."""
26402650
match event.key():
26412651
case Qt.Key.Key_Up | Qt.Key.Key_Down:
2652+
# Let the menu handle navigation
26422653
super().keyPressEvent(event)
26432654
case Qt.Key.Key_Right | Qt.Key.Key_Return | Qt.Key.Key_Enter | Qt.Key.Key_Tab:
2655+
# Activate the selection if there is one, otherwise close the completer
26442656
if action := self.activeAction():
26452657
action.trigger()
26462658
else:
26472659
self.clear()
26482660
self.close()
26492661
case Qt.Key.Key_Left | Qt.Key.Key_Escape:
2662+
# Cancel the completer
26502663
self.clear()
26512664
self.close()
26522665
case _:
2666+
# Any other keys, send back to the editor
2667+
# Also close to release the event lock before forwarding key press (#2510)
26532668
self.clear()
2654-
self.close() # Close to release the event lock before forwarding key press (#2510)
2669+
self.close()
26552670
self._parent.keyPressEvent(event)
26562671

26572672
##
2658-
# Internal Functions
2673+
# Internal Slots
26592674
##
26602675

2661-
def _emitComplete(self, pos: int, length: int, value: str) -> None:
2676+
@pyqtSlot(QAction)
2677+
def _emitComplete(self, action: QAction) -> None:
26622678
"""Emit the signal to indicate a selection has been made."""
2663-
self.insertText.emit(pos, length, value)
2679+
if isinstance(data := action.data(), CompleterAction):
2680+
self.insertText.emit(data.pos, data.length, data.value)
26642681

26652682

26662683
class BackgroundWordCounter(QRunnable):

0 commit comments

Comments
 (0)