murison murison - 1 month ago 17
C++ Question

Swapping headers in QSqlQueryModel (transpose table)

I am having a problem to properly transpose the table I recieve from db. I followed the path found here , and ended up in subclassing a QAbstractProxyModel - like described here .
unfortunatelly, it doesn't fully work, here's where the problem is:

What I have:

X | A | B
----------
1 | A1 | B1
2 | A2 | B2


What I want:

X | 1 | 2
----------
A | A1 | A2
B | B1 | B2


What I get:

X | 1 | 1
----------
A | A1 | A2
A | B1 | B2


So as you can see, the data is correctly transposed, but the headers get bad... And I really need them :(

I tried to manually set header data, but it also failed:

origModel = new QSqlQueryModel; // set query and so on
transposedModel = new TransposeProxyModel;
transposedModel->setSourceModel(origModel );
for (int i = 0; i < origModel->columnCount(); i++) {
qDebug() << "origModel->Qt::Horizontal(" << i << ")" << origModel->headerData(i, Qt::Horizontal, Qt::DisplayRole);
//transposedModel->setHeaderData(i, Qt::Vertical, origModel->headerData(i, Qt::Horizontal, Qt::DisplayRole), Qt::DisplayRole); //#try1
transposedModel->setHeaderData(i, Qt::Vertical, QVariant( "abc" ), Qt::DisplayRole); // #try2
}


No matter if I try #1, or #2 - call to setHeaderData evaluates to false...

Any ideas?

fixed as @Vinícius Gobbo A. de Oliveira pointed

Answer

Well, if you used the example code you linked you should override the default definition for the headerData method of the TransposeProxyModel class, just like this:

QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const {
    return sourceModel()->headerData(section, (orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal), role);
}

Forget about the setHeaderData and setData methods: you want a proxy model that rely on the original one!

Well, don't know exactly what's wrong, which Qt release are you using? Try this code, it works perfectly here:

#include <QtCore>
#include <QtWidgets>

class TransposeProxyModel: public QAbstractProxyModel {
public:
    TransposeProxyModel(QObject *p = 0):
        QAbstractProxyModel(p)
    {
    }
    QModelIndex mapFromSource ( const QModelIndex & sourceIndex ) const{
        return index(sourceIndex.column(), sourceIndex.row());
    }
    QModelIndex mapToSource ( const QModelIndex & proxyIndex ) const{
        return sourceModel()->index(proxyIndex.column(), proxyIndex.row());
    }
    QModelIndex index(int r, int c, const QModelIndex &ind=QModelIndex()) const{
        return createIndex(r,c);
    }
    QModelIndex parent(const QModelIndex&) const {
        return QModelIndex();
    }
    int rowCount(const QModelIndex &) const{
        return sourceModel()->columnCount();
    }
    int columnCount(const QModelIndex &) const{
        return sourceModel()->rowCount();
    }
    QVariant data(const QModelIndex &ind, int role) const {
        return sourceModel()->data(mapToSource(ind), role);
    }
    QVariant headerData(int section, Qt::Orientation orientation,
        int role = Qt::DisplayRole) const {
        return sourceModel()->headerData(section,
            (orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal),
            role);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QStandardItemModel model(3,3);
    model.setData(model.index(0,0), "1");
    model.setData(model.index(0,1), "2");
    model.setData(model.index(0,2), "3");
    model.setData(model.index(1,0), "4");
    model.setData(model.index(1,1), "5");
    model.setData(model.index(1,2), "6");
    model.setData(model.index(2,0), "7");
    model.setData(model.index(2,1), "8");
    model.setData(model.index(2,2), "9");
    model.setHeaderData(0, Qt::Horizontal, "a");
    model.setHeaderData(1, Qt::Horizontal, "b");
    model.setHeaderData(2, Qt::Horizontal, "c");
    TransposeProxyModel trans;
    trans.setSourceModel(&model);
    QSplitter split;
    QTableView *t1 = new QTableView(&split);
    t1->setModel(&model);
    QTableView *t2 = new QTableView(&split);
    t2->setModel(&trans);
    split.show();
    return a.exec();
}

Most of the code came from the link you provided, I just wrote the headerData method.