poulh / qjsontablemodel

QT Table Model that takes arrays of hashes in JSON format to populate the table
26 stars 4 forks source link

QJsonTableModel shows empty string if set as the model of an editable QComboBox #1

Open mike23456 opened 5 years ago

mike23456 commented 5 years ago

Hi there,

If i add the QJsonTableModel to a QComboBox by using the ->setModel() member function, the QlineEdit of the ComboBox will show an empty string...

Also QCompleter doesn't work for the QComboBox with this model set.

Any advice on how to fix the above issues?

poulh commented 5 years ago

Hi @mike23456 ,

Does the drop-down of the combo box show the list and just the initial entry is blank or is everything blank? Have you seen it working with a non-json model?

If you have some sample code I'd be happy to take a look.

-poul

mike23456 commented 5 years ago

Thanks for the quick reply. Yes the QComboBox shows all the QJsonTableModel entries properly. Selected items are also maintained and highlighted when QComboBox dropdown opens and the QComboBox is saving the index of new selections as well.

Previously i was setting a QSqlTableModel or a QSqlRelationalTableModel in the QComboBox and QCompleter functionality/QlineEdit used to work well.

I am in the process of transitioning a monolith app from using RDBMS as backend to SOA/microservices via several REST APIs and that's why I needed the QJsonTableModel which helped a lot.

Example code below:

    QJsonTableModel::Header customersHeader;
    customersHeader.push_back( QJsonTableModel::Heading( { {"title","id"},    {"index","id"} }) );
    customersHeader.push_back( QJsonTableModel::Heading( { {"title","Customer Number"},   {"index","number"} }) );
    customersHeader.push_back( QJsonTableModel::Heading( { {"title","Customer Name"},  {"index","name"} }) );

    QJsonTableModel *model = new QJsonTableModel(customersHeader,nullptr);

    QString json = "[{\"id\":1,\"number\":\"1\",\"name\":\"example company 1\"},{\"id\":2,\"number\":\"2\",\"name\":\"example company 2\"},{\"id\":3,\"number\":\"3\",\"name\":\"example company 3\"}]";
    QJsonDocument jsonDocument = QJsonDocument::fromJson( json );
    model ->setJson( jsonDocument );

        // customer_name is a QComboBox in a Qt UI file
        ui->customer_name->setModel(model);
        ui->customer_name->setModelColumn(2);
        ui->customer_name->completer()->setFilterMode(Qt::MatchContains);
        ui->customer_name->completer()->setCompletionMode(QCompleter::PopupCompletion);
        ui->customer_name->setInsertPolicy(QComboBox::NoInsert);

//in the below example im trying to set the QComboBox to an existing customer name:
// the below code works (it achieves setting the index, that can be verified by opening the dropdown
// menu of the QCombobox, you'll find example company 2 highlighted)

        const QString customerName = "example company 2";
        ui->customer_name->setCurrentIndex(ui->customer_name->findText(customerName));
mike23456 commented 5 years ago

Sorry I forgot to mention that the problem only happens in editable ComboBoxes. I created a simple example with QtCreator in the link below: https://we.tl/t-Ou6ffYKOj3

mike23456 commented 5 years ago

I FIXED IT! :dancing_women: in the data method, you must add a case for Qt::EditRole (the original model only has a case for Qt::DisplayRole).

Example below:

QVariant QJsonTableModel::data( const QModelIndex &index, int role ) const
{
    case Qt::EditRole:
    {
        QJsonObject obj = getJsonObject( index );
        const QString& key = m_header[index.column()]["index"];
        if( obj.contains( key ))
        {
            QJsonValue v = obj[ key ];

            if( v.isString() )
            {
                return v.toString();
            }
            else if( v.isDouble() )
            {
                return v.toDouble();//QString::number( v.toDouble() );
            }
            else
            {
                return QVariant();
            }
        }
        else
        {
            return QVariant();
        }
    }
}