For application I was using some different mechanism to create button inside custom item delegate, but now I found better way to create custom item delegate with QPushButton. So thought to share code.
Following is code for custom item delegate derived from QItemDelegate.
Update: I have uploaded following code to gitorous, Please visit this link if you want a working sample code.
#include <QItemDelegate>
class CustomItemDelegate : public QItemDelegate
{
Q_OBJECT
public:
CustomItemDelegate(QObject *parent = 0);
virtual void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const ;
virtual QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const ;
bool editorEvent(QEvent *event, QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index);
signals:
void buttonClicked(const QModelIndex &index);
private:
QStyle::State _state;
};
#include "customitemdelegate.h"
...
CustomItemDelegate::CustomItemDelegate(QObject *parent) :
QItemDelegate(parent)
{
_state = QStyle::State_Enabled;
}
void CustomItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
const QStandardItemModel* model =
static_cast<const QStandardItemModel*>(index.model());
QStandardItem* item = model->item(index.row());
QString text = item->text();
QRect rect = option.rect;
QRect textRect( rect);
textRect.setHeight( 30);
painter->drawText(textRect,text);
QRect buttonRect( rect);
buttonRect.setY(textRect.y()+ 35);
buttonRect.setHeight( 30);
QStyleOptionButton button;
button.rect = buttonRect;
button.text = text;
button.state = _state | QStyle::State_Enabled;
QApplication::style()->drawControl
(QStyle::CE_PushButton, &button, painter);
}
QSize CustomItemDelegate::sizeHint(const QStyleOptionViewItem &/*option*/,
const QModelIndex &/*index*/) const
{
//hard coding size for test purpose,
//actual size hint can be calculated from option param
return QSize(800,70);
}
bool CustomItemDelegate::editorEvent(QEvent *event,
QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index)
{
if( event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::MouseButtonRelease ) {
} else {
//ignoring other mouse event and reseting button's state
_state = QStyle::State_Raised;
return true;
}
QRect buttonRect( option.rect);
buttonRect.setY(option.rect.y()+ 35);
buttonRect.setHeight( 30);
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if( !buttonRect.contains( mouseEvent->pos()) ) {
_state = QStyle::State_Raised;
return true;
}
if( event->type() == QEvent::MouseButtonPress) {
_state = QStyle::State_Sunken;
} else if( event->type() == QEvent::MouseButtonRelease) {
_state = QStyle::State_Raised;
emit buttonClicked( index);
}
return true;
}Basically in above code, I am calculating rect where I want to draw my button and drawing QPushButton on list item using QStyleOptionButton class.And in editor event on mouse press and release event, I am checking if mouse position on click falls into my button's rect or not. If it falls inside my button's rect then I am emitting signal.
I am using item's signal as shown in below code.
CustomList::CustomList(QWidget *parent) :
QWidget(parent),_view(0)
{
_view = new QListView();
_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
//creating custom item delegate and setting it to view
CustomItemDelegate* itemDelegate = new CustomItemDelegate(_view);
_view->setItemDelegate( itemDelegate );
_view->setModel(&_model);
//connecting delegate's signal to this class's slot
connect(itemDelegate,SIGNAL(buttonClicked(QModelIndex)),
this,SLOT(listButtonClicked(QModelIndex)));
QHBoxLayout* mainLayout = new QHBoxLayout(this);
mainLayout->addWidget( _view);
//creating and adding data to model
QStandardItem* item = new QStandardItem;
item->setText("testing");
QStandardItem* item1 = new QStandardItem;
item1->setText("testing1");
_model.appendRow(item);
_model.appendRow(item1);
}
// following slot will be invoked when delegate's button is clicked
void CustomList::listButtonClicked(const QModelIndex &index)
{
qDebug() << "######### listbutton clicked ######### " << index.row();
}
Following is snap of how custom item delegate looks.