Adding CheckBox with QSqlQueryModel shown in QTableview and other columns are empty

731 views Asked by At

I am using the code in this answer to add checkbox in tableview. I want to show it in the first column.

Here is my code:

mysqlquerymodel.h

#ifndef MYSQLQUERYMODEL_H
#define MYSQLQUERYMODEL_H
#include <QObject>
#include <QMap>
#include <QModelIndex>
#include <QSqlQueryModel>

class MySqlQueryModel : public QSqlQueryModel
{
    Q_OBJECT
public:
    explicit MySqlQueryModel(QObject *parent = 0);
    Qt::ItemFlags flags(const QModelIndex & index) const;
    QVariant data(const QModelIndex & index, int role) const;
    bool setData(const QModelIndex & index, const QVariant & value, int role);
private:
    QMap<int, Qt::CheckState> check_state_map;
};
#endif // MYSQLQUERYMODEL_H

mysqlquerymodel.cpp

#include "mysqlquerymodel.h"
Qt::ItemFlags MySqlQueryModel::flags(const QModelIndex & index) const
{
    if (!index.isValid())
        return 0;
    if (index.column() == 0)
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
    return  Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant MySqlQueryModel::data(const QModelIndex & index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if(role== Qt::CheckStateRole)
    {
        if(index.column() == 0)
        {
            if (check_state_map.contains(index.row()))
                return check_state_map[index.row()] == Qt::Checked ? Qt::Checked : Qt::Unchecked;
            return Qt::Unchecked;
        }
    }
    return QVariant();
}

bool MySqlQueryModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    if(!index.isValid())
        return false;
    if (role == Qt::CheckStateRole && index.column() == 0)
    {
        check_state_map[index.row()] = (value == Qt::Checked ? Qt::Checked : Qt::Unchecked);
    }
    return true;
}

manage.cpp

void manage::on_selectBtn_clicked()
{
    QString query=QString("add_time,client_id,client_product_id,continent,country,region,city,ip,app_name,dev_os,dev_os_ver,dev_model,tusin_note,classify_note,detect_note,runtime_stats FROM ts_identify_record WHERE %1 %2 %3 %4 %5 %6 %7 ORDER BY add_time")
            .arg(timeRange()).arg(ipAddress()).arg(cellphone()).arg(product()).arg(country()).arg(province()).arg(city());
    qDebug()<<statment;
    QSqlDatabase db=QSqlDatabase::database();
    MySqlQueryModel *model=new MySqlQueryModel;
    model->setQuery(query,db);
    ui->tableView->setModel(model);
    ui->tableView->resizeColumnsToContents();
}

When I click the button, only the first column shows a checkbox and the other columns are empty. But the line count is correct and the checkbox can be clicked. It wouldn't be a problem when I just use QSqlQueryModel.

Another problem is that my select result should be 16 columns, but the first column is filled with checkbox. When I add model->insertColumn(0);, tableview shows 17 columns instead.

Why does it happen and how to fix it?

1

There are 1 answers

1
FrozenM On

The problem is that in the MySqlQueryModel::data method, you return the desired value only for the first column and only for the Qt::CheckStateRole role. For other cases, you return the QVariant(). To fix this, you have to return the necessary value for other cases. For example, you can return the value of the base class method:

QVariant MySqlQueryModel::data(const QModelIndex & index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if(role== Qt::CheckStateRole)
    {
        if(index.column() == 0)
        {
            if (check_state_map.contains(index.row()))
                return check_state_map[index.row()] == Qt::Checked ? Qt::Checked : Qt::Unchecked;
            return Qt::Unchecked;
        }
    }
    return QSqlQueryModel::data(index,role);//!!!!!
}

And, ofc, you have the constructor of MySqlQueryModel like this:

MySqlQueryModel::MySqlQueryModel(QObject *parent) : QSqlQueryModel(parent), check_state_map()
{
}

PS. Sorry for my English ;)