CopperSpice API  1.7.4
Delegate Classes

View classes are responsible for displaying the model data and processing user input during an edit. If your user interface requires displaying data in a format which is not supported in the given view class, a delegate can be used. A delegate can provide custom input capabilities and is responsible for rendering items.

The standard interface for a delegate is defined in the QAbstractItemDelegate class. Delegates are expected to be able to render their contents by implementing the paint() and sizeHint() methods. You can inherit from QAbstractItemDelegate or one of its child classes like QItemDelegate.

Editors for delegates can be implemented by using widgets to manage the editing process or by handling events directly. The first approach is covered later in this section.

Built In Delegates

The view classes provided with CopperSpice call the methods in the QItemDelegate class to provide editing capabilities. The QAbstractItemView::setItemDelegate() method can be used to specify a custom delegate for a standard view.

Custom Delegate

In the declaration shown below MySpinBoxDelegate inherits from QItemDelegate. This is the first step in creating a custom delegate which will be used to edit an integer value using a QSpinBox. The default delegate methods for displaying integer values are sufficient those these methods will not be reimplemented in our custom delegate.

A table view is constructed to display the contents of the model and the view is configured to use our custom delegate. Editor widgets are not created when the delegate is instantiated. They are only constructed when they are needed.

class MySpinBoxDelegate : public QItemDelegate
{
CS_OBJECT(MySpinBoxDelegate)
public:
MySpinBoxDelegate(QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

Editing in a Custom Delegate

When the table view needs to display an editor it calls the createEditor() method in our custom delegate class. It is not necessary to retain a pointer to the editor widget because the view will take responsibility for destroying it when it is no longer needed.

QWidget *MySpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &) const
{
QSpinBox *editor = new QSpinBox(parent);
editor->setMinimum(0);
editor->setMaximum(100);
return editor;
}

Our custom delegate must provide a method to copy data from the model into the edit widget. Data is read from the model by passing the model index and the enum value Qt::EditRole. The contents of the spin box is updated using the retrieved value.

void MySpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox *spinBox = static_cast<QSpinBox *>(editor);
spinBox->setValue(value);
}

The view is responsible for closing and destroying the editor widget. The QAbstractItemDelegate class informs the view when it has finished editing by emitting the closeEditor() signal.

Handling Data in a Custom Delegate

Continuing with our example, when the user is finished editing using the spin box, the new value needs to be saved back to the model. The view will call setModelData() in our custom delegate to store the new value. The new data needs to be saved to the model which is done by calling setData() and passing which model index to update, the new value, and the edit role.

void MySpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->interpretText();
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}