Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter with QComboBox C++

I want to create an editable QComboBox which filters results according to the search query and updates the dropdown entries accordingly.

After reading How do I Filter the PyQt QCombobox Items based on the text input? I tried to implement something similar in C++.

But I can't store anything inside the QComboBox now. Even after adding new entries through addItem() the total count remains 0.

What is the reason for this and how do I insert entries inside the QComboBox with QSortFilterProxyModel?

Here is the relevant snippet of the code:

SearchBox = new QComboBox(this);
SearchBox->setEditable(true);

// Try adding a few entries and check if they persist after changing the model
SearchBox->addItem(QString("hi"));
SearchBox->addItem(QString("bye"));

int count = SearchBox->count();    // count = 2

ProxyModel = new QSortFilterProxyModel;
ProxyModel->setSourceModel(SearchBox->model());
ProxyModel->setFilterCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
SearchBox->setModel(ProxyModel);

// Check count again
count = SearchBox->count();    // count = 0     <- Why?

// Try adding new entries
SearchBox->addItem(QString("Hi again"));

count = SearchBox->count();    // count = 0  .. So new entries don't get stored


Completer = new QCompleter(ProxyModel,this);
Completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
SearchBox->setCompleter(Completer);


QObject::connect(SearchBox->lineEdit(), SIGNAL(textChanged(const QString)), ProxyModel, SLOT(setFilterFixedString(const QString)));
QObject::connect(Completer, SIGNAL(activated(const QString &)), this, SLOT(onCompleterActivated(const QString &)));
like image 725
Nishad Avatar asked Nov 10 '22 06:11

Nishad


1 Answers

Use QStringListModel to store items. Application crashes if proxy model have no items (if filter string filters out all items)(this needs further investigation - is this completer issue or combobox). This can be fixed by not applying such filter (onTextChanged(QString text) slot). Completer completes input if theres only one item (not sure if it's ok). And sometimes checkbox doubles all items (don't know why). If this issues is critical, I think you need to write custom ComboBox from scratch and this is serious work.

{
    SearchBox = new QComboBox(this);
    SearchBox->setEditable(true);

    QStringList Items;
    Items << "hi" << "bye";
    StringListModel = new QStringListModel();
    StringListModel->setStringList(Items);

    ProxyModel = new QSortFilterProxyModel;
    ProxyModel->setSourceModel(StringListModel);
    ProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
    SearchBox->setModel(ProxyModel);

    // Check count again
    int count = SearchBox->count();    // count = 2

    // Try adding new entries
    QStringList Items_ = StringListModel->stringList();
    Items_ << "hi again";
    StringListModel->setStringList(Items_);

    count = SearchBox->count();    // count = 3

    Completer = new QCompleter(ProxyModel,this);
    Completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
    SearchBox->setCompleter(Completer);

    QObject::connect(SearchBox->lineEdit(), SIGNAL(textChanged(const QString)), this, SLOT(onTextChanged(QString)));
    QObject::connect(Completer, SIGNAL(activated(const QString &)), this, SLOT(onCompleterActivated(const QString &)));
}

void MainWindow::onTextChanged(QString Text) {
    QStringList Items = StringListModel->stringList();
    QString Item;
    foreach(Item,Items) {
        if (Item.indexOf(Text) > -1) {
            ProxyModel->setFilterFixedString(Text);
            return;
        }
    }
}
like image 76
mugiseyebrows Avatar answered Nov 15 '22 12:11

mugiseyebrows