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

Set color to tableview to certain row



  • 912281d4-b703-44b4-b566-3961d2b8e295-image.png
    Here I want to show row "GREEN" to row with important false
    and "BLUE" to row with important true

    It is fetched from database using mysql query

        tb= QSqlDatabase::addDatabase("QMYSQL","full-settings-table");
        tb.setDatabaseName("message");
        tb.setPort(3306);
        tb.setHostName("localhost");
        tb.setUserName("root");
        tb.setPassword("");
      QString command = "select * from messages;";
        {
    
      
        if(tb.open()){
            QSqlQueryModel *model = new QSqlQueryModel();
               QSqlQuery *query = new QSqlQuery(tb);
               query->prepare(command);
            if(query->exec()){
                model->setQuery(*query);
    
                ui->data->setModel(model);
    
            }else{
     //   QMessageBox::warning(this,"dataaaaaaa","not\n"+query->lastError().text());
            }
    
        }else{
    //not connected
        }
    
        }
            QSqlDatabase::removeDatabase("report"); // removing database
    
    

    I have gone through these
    https://forum.qt.io/topic/83984/how-to-set-current-cell-color-in-a-tableview-and-how-to-set-text-centeraligned
    https://forum.qt.io/topic/125874/qtableview-set-background-color-to-some-columns/3

    They all say some kind of different things Like proxy model and delegate.
    But I don't know about this topic.

    So is there simple way to implement this?


  • Lifetime Qt Champion

    Hi,

    Implement a custom QIdentityProxyModel and return the color you want for the background role of that column based on the value at the index.



  • @SGaist
    I was about to ask this question. I prepared whole question but was still searching for the answer.
    I found this one written by @VRonin (Thank you sir)

    class BackgroundBrushDelegate : public QStyledItemDelegate{
        Q_OBJECT
        Q_PROPERTY(QBrush backgroundBrush READ backgroundBrush WRITE setBackgroundBrush NOTIFY backgroundBrushChanged)
        Q_DISABLE_COPY(BackgroundBrushDelegate)
    public:
        explicit BackgroundBrushDelegate(QObject *parent = nullptr)
            : QStyledItemDelegate(parent)
        {}
        BackgroundBrushDelegate(const QBrush& brush, QObject *parent = nullptr)
            : QStyledItemDelegate(parent)
            , m_backgroundBrush(brush)
        {}
        const QBrush& backgroundBrush() const { return m_backgroundBrush; }
        void setBackgroundBrush(const QBrush& brush)
        {
            if(m_backgroundBrush==brush)
                return;
            m_backgroundBrush=brush;
            backgroundBrushChanged(m_backgroundBrush);
        }
    signals:
        void backgroundBrushChanged(const QBrush& brush);
    protected:
        void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override
        {
            QStyledItemDelegate::initStyleOption(option,index);
            option->backgroundBrush = m_backgroundBrush;
        }
    private:
        QBrush m_backgroundBrush;
    }
    

    I am using it. But I don't know how it works and other stuffs.

    In addition to @mrjj, QIdentityProxyModel is also a solution.

    In that question also You mentioned it but I don't know both of these.

    After searching about this, I found majority of answers include either https://doc.qt.io/qt-5/qidentityproxymodel.html or Delegate.

    I would be happy to get the answer which looks simple. I am not pro at it. I understand the syntax of upper code but I can't visualize it( I don't know what delegate is and what ProxyModel is 😂😂, I just know sth about model ).

    Thank You 😊☺



  • Assign background color to each item of that row.


  • Lifetime Qt Champion

    Did you already went through the Model View introduction in Qt's documentation ?



  • @SGaist I knew something about this before.
    I will read it now
    Thanks



  • I am really torn, here there are 2 solutions:
    1)

    class BackgroundBrushDelegate : public QStyledItemDelegate{
        Q_OBJECT
        Q_DISABLE_COPY(BackgroundBrushDelegate)
    public:
        explicit BackgroundBrushDelegate(QObject *parent = nullptr)
            : QStyledItemDelegate(parent)
        {}
        BackgroundBrushDelegate(const QBrush& brush, QObject *parent = nullptr)
            : QStyledItemDelegate(parent)
        {}
    protected:
        void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override
        {
            QStyledItemDelegate::initStyleOption(option,index);
            if(index.siblingAtColumn(3).data().toBool())
                option->backgroundBrush = QBrush(Qt::blue);
            else
                option->backgroundBrush = QBrush(Qt::green);
        }
    };
    

    ui->data->setItemDelegate(new BackgroundBrushDelegate(this));


    class BackgroundBrushProxy : public QIdentityProxyModel{
        Q_OBJECT
        Q_DISABLE_COPY(BackgroundBrushProxy)
    public:
        explicit BackgroundBrushProxy(QObject *parent = nullptr)
            : QIdentityProxyModel(parent)
        {}
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override{
            if(role == Qt::BackgroundRole && index.isValid()){
                if(index.siblingAtColumn(3).data().toBool())
                    return QBrush(Qt::blue);
                return QBrush(Qt::green)
            }
            return QIdentityProxyModel::data(index,role);
        }
    };
    

    And replace ui->data->setModel(model); with:

    BackgroundBrushProxy *proxy = new BackgroundBrushProxy(this);
    proxy->setSourceModel(model);
    ui->data->setModel(proxy);
    

    The decision on which is better, however, is purely philosophical (is it just user representation so use 1 or is a property of the data and 2 should be used?) and both work. The argument to siblingAtColumn is what determines what column is looked at, you probably want to handle it with a private variable + getter/setter methods or with an enum in real code to avoid it breaking when you change the code later on


    P.S.
    In your code example you are likely leaking the model and there is no reason to allocate the query on the heap. It should be:

     if(tb.open()){
            QSqlQueryModel *model = new QSqlQueryModel(this);
               QSqlQuery query(tb);
               query.prepare(command);
            if(query.exec()){
                model->setQuery(query);
    
                ui->data->setModel(model);
    

Log in to reply