Search code examples
c++mysqlqtqt5qcompleter

QCompleter, how to have the Id from a database


After a LOT of searching the web without finding the right answer, I came for help from you guys... So lets see if I can explain it.

I'm working on a UI with Qt 5, and I want a lineEdit with auto completion. I know I can use QCompleter, and it works fine. I fill the QCompleter with a query doing a for iteration. But I need to know the ID of that field.

If I'm doing a query to a database that has the Product_Name and the Product_Code, the user will type the name of the product, and in each text_edit event I fill the QCompleter with new data. But, when the user selects the Product, I want to show the code in other place. Of course, there could be two or more products with the same name but different code, so I can't look for the code after the search.

So, is there a way to have two related fields in a QCompleter?

I already try to make a QTableWidget with a hidden column (with the code) and display it right on the bottom of the QlineEdit (to simulate the Qcompleter). It looks fine, and it works... but I don't know how to add the functions that QCompleter has, like Arrow Down will jump into the table, and make it disappear when the lineEdit loses focus, but not when the table is selected.


Solution

  • You can keep additional data in the completer model:

    QMap<int, QString> data;
    data[0] = "Moscow";
    data[1] = "London";
    data[2] = "Paris";
    
    QCompleter *completer = new QCompleter(this);
    
    QStandardItemModel *model = new QStandardItemModel(completer);
    QMapIterator<int, QString> it(data);
    while (it.hasNext())
    {
        it.next();
    
        int code = it.key();
        QString name = it.value();
    
        QStandardItem *item = new QStandardItem;
        item->setText(name);
        item->setData(code, Qt::UserRole);
    
        model->appendRow(item);
    }
    
    completer->setModel(model);
    

    Then you connect to QCompleter activated(const QModelIndex &index) signal to catch autocomplete action and display additional data you want:

    connect(completer, SIGNAL(activated(QModelIndex)),
                this, SLOT(onItemActivated(QModelIndex)));
    
    void Widget::onItemActivated(const QModelIndex &index)
    {
        int code = index.data(Qt::UserRole).toInt();
    
        codeEdit->setText(QString::number(code));
    }
    

    But this approach won't work if a user doesn't use autocompletion and types the whole string. In that case you won't be able to get correct code id if there is more than one record with the same name in the DB.

    If you are trying to create some kind of a search field, I'd recommend you to display all your data in some table view and use QSortFilterProxyModel to show records matching user input in a line edit.