Mian
Mian

Reputation: 161

PyQt5: make QCompleter popup readonly

I have a QCompleter for a QLineEdit and it's working fine.

All I want is for this completer to be only read-only. So the user can only see the matches but cannot select any one of them. No highlighting, no selected item. Only a visible list of matches should be shown.

I tried for so long, but I'm still stuck and could not complete the task.

This is the code:

from PyQt5.QtWidgets import QApplication, QWidget, QCompleter, QLineEdit, QVBoxLayout
from PyQt5.QtCore import Qt, QStringListModel
import sys

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.testthislineEdit = QLineEdit()

        temp_list = ['alpha', 'beta', 'boota', 'beita']

        model = QStringListModel()
        model.setStringList(temp_list)

        completer = QCompleter()
        completer.setFilterMode(Qt.MatchContains)
        completer.setCaseSensitivity(Qt.CaseSensitivity(0))
        completer.setModel(model)
        layout = QVBoxLayout()
        layout.addWidget(self.testthislineEdit)
        self.setLayout(layout)

        self.testthislineEdit.setCompleter(completer)

if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()

try:
    sys.exit(app.exec_())
except SystemExit:
    print('Closing Window...')

Upvotes: 1

Views: 185

Answers (1)

ekhumoro
ekhumoro

Reputation: 120578

One way to do this would be to use a custom item-view and selection-model with reimplemented methods that disable all the default selection, mouse and keyboard handling. It will also be necessary to ensure the custom selection-model is linked to the completer's internal proxy model.

Here is a working demo based on your example:

from PyQt5.QtWidgets import QApplication, QWidget, QCompleter, QLineEdit, QVBoxLayout, QListView
from PyQt5.QtCore import Qt, QStringListModel, QItemSelectionModel, QAbstractProxyModel
import sys

class SelectionModel(QItemSelectionModel):
    def select(self, *args, **kwargs):
        # disable selection
        pass

    def setCurrentIndex(self, *args, **kwargs):
        # disable current index
        pass

class ListView(QListView):
    def setSelectionModel(self, model):
        # link custom selection model to completer proxy model
        super().setSelectionModel(SelectionModel(model.model(), self))

    def mousePressEvent(self, event):
        # ignore mouse events
        self.close()

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.testthislineEdit = QLineEdit()

        temp_list = ['alpha', 'beta', 'boota', 'beita']

        model = QStringListModel()
        model.setStringList(temp_list)

        completer = QCompleter()
        completer.setFilterMode(Qt.MatchContains)
        completer.setCaseSensitivity(Qt.CaseSensitivity(0))

        # set custom popup
        completer.setPopup(ListView(self))

        completer.setModel(model)
        layout = QVBoxLayout()
        layout.addWidget(self.testthislineEdit)
        self.setLayout(layout)

        self.testthislineEdit.setCompleter(completer)

if __name__ == "__main__":

    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()

    try:
        sys.exit(app.exec_())
    except SystemExit:
        print('Closing Window...')

Upvotes: 2

Related Questions