Search code examples
c++qtqt5qcomboboxqcompleter

How to use a custom validation function for a QCompleter in a QComboBox


I have a string matching function to be used for searching for names that is more advanced than QString::contains() (e. g. when you search for "mueller", it will match "Müller").

I'd like to use this function to search inside a QComboBox. The default completion almost does what I need: If I do

combobox->setEditable(true);
combobox->setInsertPolicy(QComboBox::NoInsert);
combobox->completer()->setCompletionMode(QCompleter::PopupCompletion);

and type some text in the QComboBox's lineedit, the popup pops up, only showing entries starting what has been typed.

This is what I want, but I would like the QCompleter to evaluate matches using my search function rather than the QString::startsWith() that is apparently used here (and setting the mode to Qt::MatchContains is better but still not sufficient).

Is there any way to customize the completer's search function?

Thanks for all help!


Solution

  • I ended up using an own QCompleter and set it for the QComboBox's QLineEdit. The completer does not use the combobox's model, but an own one, which is filled with data everytime the entered text changes.

    Can be done as follows:

    m_matchingNames = new QStringListModel(this);
    m_nameCompleter = new QCompleter(m_matchingNames, this);
    m_nameCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
    m_playersSelect->setEditable(true);
    m_playersSelect->setInsertPolicy(QComboBox::NoInsert);
    m_playersSelect->setCompleter(0);
    m_playersSelect->lineEdit()->setCompleter(m_nameCompleter);
    connect(m_playersSelect->lineEdit(), &QLineEdit::textEdited, this, &ScorePage::nameSearchChanged);
    

    and

    void ScorePage::nameSearchChanged(const QString &text)
    {
        QStringList possibleNames;
        for (const QString &name : m_availableNames) {
            if (checkMatch(name, text)) {
                possibleNames << name;
            }
        }
        m_matchingNames->setStringList(possibleNames);
    }
    

    Most probably not the most prerformant solution, but it works :-)

    One then can also connect to QCompleter::activated() to process what has been chosen from the list and e. g. do a QComboBox::setCurrentIndex() or such.