Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add virtual column to Qt SQL model using a proxy

Tags:

c++

qt

I display an SQL table in a view using a QSqlTableModel.

I want to display an additional status column based on the row data, for that I use a custom QIdentityProxyModel where I increase the columnCount and return data for that new virtual column which does not exist in the QSqlTableModel.

int MyProxyModel::columnCount(const QModelIndex& parent) const
{
    return sourceModel() ? (sourceModel()->columnCount() + 1) : 0;
}

QVariant MyProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (section == columnCount()-1 && 
        orientation == Qt::Horizontal &&
        role == Qt::DisplayRole) 
    {
        return tr("MyHeader");
    }

    return QIdentityProxyModel::headerData(section, orientation, role);
}

QVariant MyProxyModel::data(const QModelIndex &proxyIndex, int role) const
{
    qDebug() << "data " << proxyIndex.row() << proxyIndex.column(); 
    // ...never called for my extra column (== columnCount()-1)

    if (proxyIndex.column() == columnCount()-1 && role == Qt::DisplayRole)
        return QString("I am virtual");

    return QIdentityProxyModel::data(proxyIndex, role);
}

Edit: I changed the code for something more simple regarding to the comments. I still have the same problem.

My problem is that the view never asks data for my virtual column, it calls data() for all other columns of the actual SQL table but not the last virtual one, what have I missed ? Also, the header data is working well for my extra column, the problem is only with the data. The view draws the extra column, but content is empty (even alternating row background is not painted). Thx !

like image 707
ymoreau Avatar asked Nov 06 '25 02:11

ymoreau


2 Answers

The view needs to get the QModelIndex objects for the virtual column, so I also needed to override the index function in the proxy :

QModelIndex MyProxyModel::index(int row, int column, const QModelIndex &parent) const
{
    if (column == columnCount()-1)
        return createIndex(row, column);

    return QIdentityProxyModel::index(row, column);
}

I didn't mind the parent because I only have a table (from database), though I do not know how it could be dealt with if needed because createIndex does not allow to specify a parent.

like image 171
ymoreau Avatar answered Nov 07 '25 16:11

ymoreau


The m_mySqlTableColumnCount member is unnecessary. You'd have to ensure it's always correct by listening to the source model's signals that update the column count. Alas, it's unnecessary. You want to pass the column count request through to the source model:

int MyProxyModel::columnCount(const QModelIndex& parent) const
{
    return sourceModel() ? (QIdentityProxyModel::columnCount() + 1) : 0;
}

Then:

QVariant MyProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (section == columnCount()-1 && 
        orientation == Qt::Horizontal &&
        role == Qt::DisplayRole) 
    {
        return tr("MyHeader");
    }    
    return QIdentityProxyModel::headerData(section, orientation, role);
}

QVariant MyProxyModel::data(const QModelIndex &proxyIndex, int role) const
{
    if (proxyIndex.column() == columnCount()-1) {
      qDebug() << proxyIndex.row() << proxyIndex.column();
      ...
    }
    return QIdentityProxyModel::data(proxyIndex, role);
}
like image 25
Kuba hasn't forgotten Monica Avatar answered Nov 07 '25 14:11

Kuba hasn't forgotten Monica