bgColor row in QSqlRelationalTableModel and QSqlQueryModel seems to be impossible



  • I am trying both QSqlRelationalTableModel and QSqlQueryModel to view records from a database in a QtableView, but when I want to do something as simple as setting a background color on a row, i bang my head on the wall,... two days, and still nothing is working... i cant believe how impossible it is to find a simple solution to this. I have read so many messages on forums and various websites, and there is nothing that works, it all suggests the same things that does not work. You can for example not use:

    model->setData(index, QVariant(QColor(Qt::yellow)), Qt::BackgroundRole);

    ... because both QSqlRelationalTableModel and QSqlQueryModel is ignoring Qt::BackgroundRole. QSqlQueryModel is read only, so only model->data() works for getting data. QSqlRelationalTableModel can model->setData() but it only cares about Qt::EditRole, and ignores all I try to do with background color.

    I have found some extremely long and complicated solutions, that might work, but I cant believe that i have to write several pages of code to set a freaking background color on a row.

    Please, if someone knows how to do this, I would really appreciate some help on this.
    Thank you,



  • I've had good results doing this by subclassing QSortFilterProxyModel and overriding the data() function.

    If all you want is alternating background colours, the QTableView has the alternatingRowColors attribute that you can set.

    Mike



  • @mjsurette
    I want the shortest possible code to set the background color of some rows. For example all rows where the third column is empty should have background color light green.

    The sort and filtering is not something I want to have on the view, and if I am going to do all this, then it seems shorter to create my own model. I just cant believe that i have to do all that just to put a color on a row...

    There has to be an easier way to do this... ????


  • Qt Champions 2017

    Subclass QIdentityProxyModel and override QAbstractItemModel::data, then you can return the color for your data when the Qt::BackgroundRole is requested.

    Alternatively, create a delegate and paint your data however you like.



  • @mjsurette
    OK - so there are no ways to do it, without making a new class.

    I'm still working on this, and please let me know if there is a shorter way to do it than this. I think what I have is the shortest in amount of code, but please let me know if it can be shorter.

    In the .h file:

    #include <QSqlQueryModel>
    class CustomSqlModel : public QSqlQueryModel
    {
        Q_OBJECT
    public:
        CustomSqlModel(QObject *parent = 0);
        QVariant data(const QModelIndex &item, int role) const Q_DECL_OVERRIDE;
    };
    

    In the .cpp file:

    #include "customsqlmodel.h"
    CustomSqlModel::CustomSqlModel(QObject *parent)
        : QSqlQueryModel(parent)
    {
    }
    QVariant CustomSqlModel::data(const QModelIndex &index, int role) const
    {
        QVariant value = QSqlQueryModel::data(index, role);
        if (role == Qt::BackgroundRole && index.row() == 1)
            return QVariant::fromValue(QColor(Qt::blue));
        return value;
    }
    


  • The problem is that i am inside the data() function when I am evaluating if I want to paint a row with a background color. I can not see the other colums from inside data(), because in data() i am on a specific cell, and all i have is the index of that cell and the role.

    So how can I find out if for example cell / column number 2 on the current row has no text ? ... from inside the data() ????

    I posted a solution under a more precise topic / thread: :lSqlModel::data() - select based on value in other cells

    I'm not entirely satisfied with that solution, so If you know a better way, please let me know.



  • @A.K.G.
    This is where the sibling() function comes in handy.

    {
        QModelIndex sib= index.sibling(index.row(),1);
        bool sibValue= sib.data().toBool();
        if (role == Qt::BackgroundRole && sibValue)
            return QVariant::fromValue(QColor(Qt::blue));
        return value;
    }
    

    HTH

    Mike



  • @mjsurette there we go !!! ha ha ha, i knew there had to be something more... i cant believe i missed that one. I actually red it, and thought it was for something else, like if you are roaming around in a tree structure... anyway, THANK YOU !!



  • This is what i ended up doing:

        QVariant CustomSqlModel::data(const QModelIndex &index, int role) const
        {
            if (role == Qt::BackgroundRole && QSqlQueryModel::data(this->index(index.row(), 1), Qt::DisplayRole).toString().isEmpty()){
                return QColor(Qt::yellow);
            }
            return QSqlQueryModel::data(index, role);
        }
    


  • Since none of your indexes have children, implementing support for other roles is quite straightforward as suggested by @kshegunov

    This is the implementation I had around for this cases (my use case was with QStringListModel but it should be the same

    http://pastebin.com/kzeUenzJ

    with this you can use model->setData(index, QVariant(QColor(Qt::yellow)), Qt::BackgroundRole); with QSqlQueryModel and QSqlRelationalTableModel


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.