简体   繁体   中英

QCompleter setModel crashes application

I have table widget, where one of the columns needs to have text autocopletion.

Each time the user request a new row I run this code for that column:

    else if (i == COLUMN_DESCRIPICION){
        QLineEdit *le = new QLineEdit(this);
        QStringList list = dbManager.getProductListStringsOnly();
        QCompleter *completer = new QCompleter(list,le);
        completer->setCaseSensitivity(Qt::CaseInsensitive);
        completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
        le->setCompleter(completer);
        ui->twReceiptItems->setCellWidget(rowindex,i,le);
    }

So far so good. Now the user might need to input a new item to the system. If he does, then that Item also needs to be in the list of EXISTING rows. So to update the QCompleter word list I run this:

void MainView::updateProductList(){

    if (ui->twReceiptItems->rowCount() == 0) return;

    QStringList list = dbManager.getProductListStringsOnly();

    for (qint32 i = 0; i < ui->twReceiptItems->rowCount(); i++){
        qDebug() << 1;
        QLineEdit *le = static_cast<QLineEdit*>(ui->twReceiptItems->cellWidget(i,COLUMN_DESCRIPICION));
        qDebug() << 2 << (le == nullptr);
        QCompleter *completer = le->completer();
        qDebug() << 3 << (completer == nullptr);
        QStringListModel *model = static_cast<QStringListModel*>(completer->model());
        qDebug() << 4 << (model == nullptr);
        if (model == nullptr) model = new QStringListModel();
        qDebug() << 5 << (model == nullptr);
        model->setStringList(list);
        qDebug() << 6;
        completer->setModel(model);
        qDebug() << 7;
        le->setCompleter(completer);
        qDebug() << 8;
    }

}

The program crashes between qDebug line 6 and 7. But I can't figure out what I'm doing wrong.

You're trying to replace the completer model using a pointer to its current one. When you call setModel a delete on the current object is called, and it happens to be the very same object you're trying to set as the new one.

Here you set a pointer to the current model:

QStringListModel *model = static_cast<QStringListModel*>(completer->model());

here you set it back:

completer->setModel(model);

Just use a new one, instead, ie

completer->setModel(new QStringListModel(list));

or, even better

le.completer()->setModel(new QStringListModel(list));

Just a footnote: don't use static_cast for up-casting. C++ has a specific cast for that, dynamic_cast , and Qt even has qobject_cast for QObject derivatives.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM