Facing issue with paint method for QPushButton when used QStyledItemDelegate

Viewed 40

I have implemented PushButtonDelegate for a column in QTableView since we are using QSortFilterProxyModel to filter the table view. I am setting this delegate to one of the columns as shown below...

table_->setItemDelegateForColumn(11, new PushButtonDelegate(table_));

The PushButtonDelegate is derived from QStyledItemDelegate and I have overridden createEditor, setEditorData, setModelData, updateEditorGeometry, and paint methods as shown below...

PushButtonDelegate::PushButtonDelegate(QObject* parent) :QStyledItemDelegate(parent)
{
    if (const auto table_view = qobject_cast<QTableView*>(parent))
    {
        my_widget_ = table_view;
        btn_ = new QPushButton(button_text_, my_widget_);
        btn_->hide();
        //my_widget_->setMouseTracking(true);
        connect(my_widget_, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(CellEntered(QModelIndex)));
        is_one_cell_in_edit_mode_ = false;
    }
}
QWidget* PushButtonDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        const auto btn = new QPushButton(parent);
        const auto value = index.data().toString();
        btn->setCheckable(true);
        btn->setChecked(value == "Yes" ? true : false);
        btn->setFocusPolicy(Qt::NoFocus);
        connect(btn, SIGNAL(clicked(bool)), this, SLOT(UpdateUseButton(bool)));

        return btn;
    }
    else
    {
        return QStyledItemDelegate::createEditor(parent, option, index);
    }
}

void PushButtonDelegate::UpdateUseButton(bool checked) const
{
    if (const auto selection_button = dynamic_cast<QPushButton*>(sender()))
    {
        const QString value = selection_button->text();
        selection_button->setText(value == "Yes" ? "No" : "Yes");
        selection_button->setChecked(value == "Yes" ? false : true);
        selection_button->setCheckable(true);
    }
}

void PushButtonDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        const auto value = index.model()->data(index, Qt::EditRole).toString();
        const auto pb = dynamic_cast<QPushButton*>(editor);
        pb->setChecked(value == "Yes" ? true : false);
        pb->setText(value);
        pb->setCheckable(true);
    }
    else
    {
        QStyledItemDelegate::setEditorData(editor, index);
    }
}

void PushButtonDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        const auto pb = dynamic_cast<QPushButton*>(editor);
        const auto value = pb->text();
        pb->setChecked(value == "Yes" ? true : false);
        pb->setCheckable(true);
        const auto ptr = dynamic_cast<QSortFilterProxyModel*>(model);
        ptr->setData(index, value, Qt::EditRole);
    }
    else
    {
        QStyledItemDelegate::setModelData(editor, model, index);
    }
}

void PushButtonDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        painter->save();
        btn_->setGeometry(option.rect);
        const auto value = index.data().toString();
        btn_->setCheckable(true);
        btn_->setText(value);
        btn_->setChecked(value == "Yes" ? true : false);

        if (value == "Yes")
            painter->fillRect(option.rect, option.palette.highlight());
        else
            painter->fillRect(option.rect, option.palette.shadow());

        const QPixmap map = btn_->grab();
        painter->drawPixmap(option.rect.x(), option.rect.y(), map);

        painter->restore();
    }
    else
    {
        QStyledItemDelegate::paint(painter, option, index);
    }
}

void PushButtonDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    editor->setGeometry(option.rect);
}

I am facing the following issues...

  1. I have to click on the button 3 times to change the text from "No" to "Yes".
  2. The highlighting of the buttons is not proper as shown (Button should be highlighted when the text is yes)...

enter image description here

Need help...

0 Answers
Related