Reputation: 345
First time I'm trying to use a QCompleter
in PyQt5.
My data is a list of dictionary objects with two text fields. I'm using a subclassed QAbstractTableModel
to return a combined string in column 0. I'm giving this to a QCompleter
in a QLineEdit
. But when I try to complete, it gives me an empty popup. When I press up/down, it does go through the options (I have checked using print()
statements in the data()
method of my QAbstractTableModel
) but only occasionally does it put a completed string in the text of the QLineEdit
.
Note the popup stays empty, even when it puts a completed string in the text.
I want a "normal" popup list, like all the examples I can find online show. What am I doing wrong?
allSubjects = []
def loadAllSubjects():
global allSubjects
allSubjects = []
cur.execute('''
select trim(sub_code), trim(sub_desc)
from subtab
where cmpy_code='01' and active_flg='Y'
order by sub_desc, sub_code
''')
row = cur.fetchone()
while row:
(sub_code, sub_desc) = row
allSubjects.append({
"code": sub_code,
"desc": sub_desc,
})
row = cur.fetchone()
class SubjectTableModel(QtCore.QAbstractTableModel):
def __init__(self):
super(SubjectTableModel, self).__init__()
def rowCount(self, index) -> int:
global allSubjects
return len(allSubjects)
def columnCount(self, index) -> int:
return 4
def data(self, index, role):
# print(f"data({index.row()},{index.column()})")
global allSubjects
sub = allSubjects[index.row()]
# print(sub)
colidx = index.column()
if colidx == 0:
return sub["desc"] + " (" + sub["code"] + ")"
elif colidx == 1:
return sub
elif colidx == 2:
return sub["code"]
elif colidx == 3:
return sub["desc"]
def headerData(self, colidx, orientation, role):
if colidx == 0:
return "Search"
elif colidx == 1:
return "Code"
elif colidx == 2:
return "Description"
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.resize(1000, 800)
subLabel = QLabel("Subject:")
subSearch = QLineEdit()
subCompleter = QCompleter()
subCompleter.setModel(SubjectTableModel())
subCompleter.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
# subCompleter.setModelSorting(QCompleter.CaseInsensitivelySortedModel)
subSearch.setCompleter(subCompleter)
subPart = QHBoxLayout()
subPart.addWidget(subLabel)
subPart.addWidget(subSearch)
(...)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
loadAllSubjects()
app.exec()
Edit: I know it has something to do with using a QAbstractTableModel
for my data. If I just use a list of strings instead, it works fine.
Upvotes: 0
Views: 108
Reputation: 196
You can limit what to return based on the role
parameter of the data
method:
def data(self, index, role):
global allSubjects
sub = allSubjects[index.row()]
if role == Qt.DisplayRole or role == Qt.EditRole:
colidx = index.column()
if colidx == 0:
return sub["desc"] + " (" + sub["code"] + ")"
elif colidx == 1:
return sub["code"]
elif colidx == 2:
return sub["desc"]
Qt.DisplayRole controls the text to show up in the popup, while Qt.EditRole controls the actual text inserted into the line edit.
Upvotes: 0