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...
- I have to click on the button 3 times to change the text from "No" to "Yes".
- The highlighting of the buttons is not proper as shown (Button should be highlighted when the text is
yes)...
Need help...
