PDA

View Full Version : QCompleter with dynamic data model



Chris Slominski
15th September 2017, 16:04
Using Qt 4.8.5

I want a dynamic data model for a QCompleter installed in a QLineEdit. I connect the QLineEdit::textEdited signal to my own function that updates the model, which is my sub-class of QAbstractListModel. It begins as an empty model, but fills itself out on the third keystroke. No completions occur. If I full populate the model when constructed, all works. See code below. I do not know how to notify the QCompleter that the model has changed. I used 'beginResetModel()/endResetModel()' as a try.


// This slot is connected to the QLineEdit::textEdited signal.
void MyaNameModel::Update(const QString &text)
{
if (text.size() < 3)
{ if (!names.empty())
{ m_names.clear(); // Clear data model's collection of names.

// Notify QCompleter that model has changed.
beginResetModel();
endResetModel();
}
}
else if (m_names.empty())
{ // This extracts information from an external repository via in-house API.
// It fills the container of names.
m_ap.MatchChannel(Glob((text + "*").toAscii().data()), m_names);

// Notify QCompleter that model has changed.
beginResetModel();
endResetModel();
}
}

d_stranz
20th September 2017, 00:34
Typically, you call beginModelReset(), change the data, then call endModelReset(). In your case you are changing the data then calling the two reset methods. It probably doesn't make a difference in this particular case, but you should change your code to do it correctly anyway.

I assume you have implemented the data() method for your model. The text displayed by the QCompleter comes from the value returned by the Qt::EditRole role. Be sure your data() method is returning values for this role.

Finally, ensure you are calling QCompleter::setCompletionPrefix() with the QLineEdit text.

BUT the problem with what you are doing is that what you are trying to do manually, looking up partial matches to names from a global database and then supplying them to QCompleter as completion candidates is exactly what QCompleter itself is designed to do.

What you should be doing is giving QCompleter the entire list of names (preferably sorted) (i.e. m_ap.MatchChannel( Glob( "*" ), m_names )) once. All your slot needs to do at that point is to tell QCompleter to set the prefix string (QCompleter::setCompletionPrefix()) to whatever the current text is in the line edit. QCompleter will filter the list of names and send back the correct subset, all without your "help".