Reputation: 37
I'm trying to build an IntelliSense-like code completion system inside a QPlainTextEdit using PySide2. However, I'm facing issues with focus management and hiding the QListWidget when it pops up. The goal is for the popup to appear when the user is typing, allowing them to continue typing into the text editor while the popup is visible, and then hide the popup when needed (e.g., pressing the Escape key or moving the cursor away).
Here are the main issues I'm facing:
Focus Issue: I'm using self.completer_list.setFocusPolicy(Qt.NoFocus) to prevent the popup from taking focus, but when using Qt.Popup, the focus still shifts to the QListWidget, and the rest of the program becomes unresponsive until I interact with the popup.
Popup Hiding Issue: I'm using self.completer_list.hide() to hide the popup, but it doesn't always hide properly or doesn't respond well when clicking outside or when the cursor moves.
What might I be doing wrong in my code?
This is part of my code:
self.temp_completer_list = ["for", "while", "if", "else", "elif", "def",
"class", "import", "from", "return", "try",
"except", "finally"]
self.completer_list = QListWidget()
self.completer_list.addItems(self.temp_completer_list)
self.completer_list.setWindowFlag(Qt.Popup)
self.completer_list.hide()
self.textChanged.connect(self.show_completer_list)
def show_completer_list(self):
"""CURSOR TO POPUP"""
cursor = self.textCursor()
pos = self.cursorRect(cursor).bottomRight()
global_pos = self.mapToGlobal(pos)
self.completer_list.move(global_pos)
self.completer_list.show()
self.completer_list.setFocusPolicy(Qt.NoFocus)
Upvotes: 0
Views: 38
Reputation: 37
I did it with the using "Jedi" like tihs:
# QCompleter oluştur
self.completer = QCompleter(self)
self.completer.setCompletionMode(QCompleter.PopupCompletion)
self.completer.setWidget(self)
# Dinamik olarak güncellenecek model
self.model = QStringListModel()
self.completer.setModel(self.model)
# İmleç pozisyonuna göre tamamlama popup'ını göster
self.textChanged.connect(self.show_completer)
# Completer'den bir öneri seçildiğinde, insert_completion fonksiyonunu çağır.
self.completer.activated.connect(self.insert_completion)
def show_completer(self):
"""Tamamlama popup'ını göster"""
cursor = self.textCursor()
cursor.select(cursor.WordUnderCursor)
current_code = self.toPlainText() # Şu anki metni al
line, col = cursor.blockNumber() + 1, cursor.columnNumber() # Jedi'ye göndermek için pozisyonu al
# Jedi'yi kullanarak tamamlama önerileri al
script = jedi.Script(current_code)
completions = script.complete(line, col) # Satır ve sütun numarasını burada kullanıyoruz
# Eğer tamamlama önerileri varsa, popup'ı göster
if completions:
completion_list = [comp.name for comp in completions] # Önerileri listeye dönüştür
self.model.setStringList(completion_list)
rect = self.cursorRect()
rect.setX(rect.x() + 35) # Popup'ı 2 birim sağa kaydırıyoruz
rect.setWidth(self.completer.popup().sizeHintForColumn(0) + 100) # Popup genişliği
# Popup için opaklık ayarı yapıyoruz
opacity_effect = QGraphicsOpacityEffect(self.completer.popup())
opacity_effect.setOpacity(0.9) # %90 opaklık
self.completer.popup().setGraphicsEffect(opacity_effect)
self.completer.complete(rect) # Popup'ı göster
else:
self.completer.popup().hide() # Eğer öneri yoksa popup'ı gizle
def keyPressEvent(self, event):
cursor = self.textCursor()
if self.completer.popup().isVisible():
if event.key() in (Qt.Key_Enter, Qt.Key_Return):
selected_item = self.completer.popup().currentIndex().data()
if selected_item:
self.insert_completion(selected_item)
self.completer.popup().hide()
return # Varsayılan işleyiciyi engelle
elif event.key() == Qt.Key_Space or event.key() == Qt.Key_Escape:
self.completer.popup().hide()
return
Upvotes: -1