Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt add column to QSqlTableModel and QSortFilterProxyModel



  • I want to add a Column to QTableView and presenting some calculations there. The column is inserted successfully but I cannot set column data. It create somehow uneditable Column?

    m=new QSqlTableModel();
    m->database().open();
    m->setTable("trans");
    m->select();
    
    pm = new QSortFilterProxyModel;
    pm->setSourceModel(m);
    pm->insertColumns(4,1);
    
    for (int i = 0; i < pm->rowCount(); ++i) {
        if(pm->data(pm->index(i,1)).toString()==id){
            pm->setData(pm->index(i,4),pm->data(pm->index(i,3)).toInt()*-1);
        }
        if(pm->data(pm->index(i,2)).toString()==id){
            pm->setData(pm->index(i,4),pm->data(pm->index(i,3)).toInt()*1);
        }
    }
    
    ui->tableViewTransactions->setModel(pm);
    


  • @alex20 said in Qt add column to QSqlTableModel and QSortFilterProxyModel:

    I hope I'm not wrong about this, but you can't do that. I imagine a QSortFilterProxyModel just has to find its data in the source model, it does not offer its own data storage.

    Check the setData() statements' return result to verify you are getting false. While you're there check the insertColumns() to see whether it was even accepted?

    I do not believe you can add your own columns into a QSqlTableModel, you can only use those returned by the query/table. Please let me know if that is not the case!


  • Lifetime Qt Champion

    Hi,

    @JonB is not far from the truth. If you go the proxy way, you need to provide a custom proxy model and reimplement the data method to return the calculated value you want to show in that column.
    Reimplement also the column count to add the additional column.

    Depending on your application, you can also subclass QSqlTableModel and add the column there.



  • @SGaist said in Qt add column to QSqlTableModel and QSortFilterProxyModel:

    reimplement the data method to return the calculated value

    For the record, so that I understand. Let's suppose the extra columns are not calculated (want to just add some actual local data). At this point I presume you would have to include your own (new) columns' data storage (as an a array or whatever) in your custom proxy model. Then its data()/setData() would have to act on proxy's own extra data or pass through to source model depending on column. Is that correct?


  • Lifetime Qt Champion

    That's correct.

    Call the base class implementation unless it's your additional column that is requested.



  • @JonB Yes you are right.
    @SGaist You mean it is not possible to modifying the Model of the proxy and we should reimplement an other model and add our extra data to it.

    Thanks @JonB and @SGaist I will start to write a function.



  • @alex20 said in Qt add column to QSqlTableModel and QSortFilterProxyModel:

    @SGaist You mean it is not possible to modifying the Model of the proxy and we should reimplement an other model and add our extra data to it.

    If I may make so bold as to reply on @SGaist's behalf to check my understanding, I'm sure I will be corrected if I have misunderstood :)

    Yes and No. You cannot modify the QSqlTableModel model (unless you subclass), and the QSortFilterProxyModel you are using does not offer storage for extra columns you are trying to store in.

    In your case (unlike my question) the data you want to store is calculated from other column data in the row, as per your code. Do not try/bother using setData() to actually store the new column's values anywhere. Instead, derive your own QAbstractProxyModel. Override the data() method (suitable roles) to return the calculated result if being asked for your column, otherwise return the QSqlTableModel (via QAbstractProxyModel::sourceModel())'s data().

    Alternatively, if you don't want to go down any proxy route, you can instead change your underlying table model from the plain QSqlTableModel you are using now and do the data() work there, or add storage if you really want to setData(). I didn't know that was OK to do, you'd have to be careful about how you would allow editing if you currently do so.


Log in to reply