Всю жизнь пользовался только QTableWidget и горя не знал, но тут попалась мне программа с QTableView, завязанной на модель QSqlTableModel.
Оказалось, добавить человеческие чекбоксы через делегаты, не так то просто. Предлагаю свое решение проблемы, т.к. нигде ничего не нашел толкового.
1. Добавление чекбоксов в третью колонку таблицы ui->table в конструкторе
for( int i=0; i<model.rowCount(); i++ )
{
QWidget *widget = new QWidget();
QCheckBox *chBox = new QCheckBox();
QHBoxLayout *layout = new QHBoxLayout;
layout->setMargin(0);
layout->setSpacing(0);
layout->addWidget(chBox);
layout->setAlignment( Qt::AlignCenter );
widget->setLayout( layout );
ui->table->setIndexWidget( model.index(i, 3), widget );
if( model.data( model.index(i, 3) ).toBool() )
chBox->setChecked( true );
else
chBox->setChecked( false );
connect( chBox, SIGNAL(clicked(bool)), this, SLOT(onCheckBoxChecked(bool)) );
}
Здесь мы создаем виджет и лайаут для выравнивания чекбокса по центру, добавляем родительский виджет в таблицу и связываем сигнал чекбокса со слотом. model - QSqlModelTable
2. Код обработчика сигнала чекбокса:
void ClassName::onCheckBoxChecked(bool isChecked)
{
QCheckBox *widget = qobject_cast<QCheckBox*>(sender());
for( int i=0; i<model.rowCount(); i++ )
{
if( ui->table->indexWidget(model.index(i, 3)) != NULL )
{
QWidget *cellWidget = qobject_cast<QWidget*>(ui->table->indexWidget(model.index(i, 3)))->layout()->itemAt(0)->widget();
if( widget == qobject_cast<QCheckBox*>(cellWidget) )
{
if( isChecked )
model.setData( model.index(i, 3), true );
else
model.setData( model.index(i, 3), false );
model.submitAll();
}
}
}
}
Здесь ничего хитрого, используем QObject::sender() для получения ссылки на объект, который испустил сигнал.
3. Теперь нужен код для добавления и удаления строк из таблицы.
Приведу кусок кода для удаления строки.
Сначла удаляем все чекбоксы после удаления выделенной строки:
if( !model.removeRows( selectedRow,1 ) )
{
// ERROR
}
else
{
for( int i=0; i<model.rowCount(); i++ )
ui->table->indexWidget( model.index(i,3) )->deleteLater();
}
Далее нам надо занести в базу изменения в модели и обновить ее, чтобы изменения отобразились на QTableView:
model.submitAll();
model.select();
Дальше остается заново добавить все чекбоксы, как в конструкторе.
Добавление строк в таблицу осуществляется по тому же принципу. При добавлении и удалении строк в таблице приходится каждый раз удалять все чекбоксы и добавлять заново, потому что при вызове QSqlTableModel::select() обновляется вся таблица. Не думаю, что стоит переживать по этому поводу, работа с базой все равно стоит дороже наших чекбоксов.
В принципе все. Остается убрать надписи true/false из ячеек с чекбоксами.
Я не стал долго ломать голову, и вам не советую.
Можно написать вот такой простенький делегат, который будет менять цвет текста и фона ячеек колонки на базовый:
class CheckBoxDelegate : public QItemDelegate
{
Q_OBJECT
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem op(option);
QPalette palette;
op.palette.setColor(QPalette::Text, palette.color(QPalette::Base));
op.palette.setColor(QPalette::Window, palette.color(QPalette::Base));
op.palette.setColor(QPalette::Highlight, palette.color(QPalette::Base));
op.palette.setColor(QPalette::HighlightedText, palette.color(QPalette::Base));
QItemDelegate::paint(painter, op, index);
}
};
Не забываем добавить делегат в конструкторе:
ui->table->setItemDelegateForColumn( 3, new CheckBoxDelegate );
Готово. Имеем чекбоксы по центру ячейки, которые нажимаются одним кликом и всегда видны, при этом никакого текста в ячейке нет.