PDA

View Full Version : A checkbox only column in QTableView



gfernandes
28th January 2014, 12:51
Hi,

I have table in Sqlite database which I display using QTableview and QSqlQueryModel. The first column needs to have a header which is a checkbox and all the items in the column needs to be checkbox too. Since the checkbox needs to be centered, I need to use a delegate to paint it.

I have painted checkbox using the following code. This creates checkboxes, but they cannot be checked or unchecked.


static QRect CheckBoxRect(const QStyleOptionViewItem &view_item_style_options) {
QStyleOptionButton check_box_style_option;
QRect check_box_rect = QApplication::style()->subElementRect(
QStyle::SE_CheckBoxIndicator,
&check_box_style_option);
QPoint check_box_point(view_item_style_options.rect.x() +
view_item_style_options.rect.width() / 2 -
check_box_rect.width() / 2,
view_item_style_options.rect.y() +
view_item_style_options.rect.height() / 2 -
check_box_rect.height() / 2);
return QRect(check_box_point, check_box_rect.size());
}


CheckBoxDelegate::CheckBoxDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{
}

void CheckBoxDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const {
bool checked = index.model()->data(index, Qt::DisplayRole).toBool();

QStyleOptionButton check_box_style_option;
check_box_style_option.state |= QStyle::State_Enabled;
if (checked) {
check_box_style_option.state |= QStyle::State_On;
} else {
check_box_style_option.state |= QStyle::State_Off;
}
check_box_style_option.rect = CheckBoxRect(option);

QApplication::style()->drawControl(QStyle::CE_CheckBox,
&check_box_style_option,
painter);
}

I still do not have a clear idea how to go about it. I read somewhere that I need to re-implement data(), setdata() and flags() of QSqlQueryModel. The following code shows how I use the QSqlQueryModel for QTableView. Could you please tell me how to go about it? Any help is appreciated.


//Load the tableview with the database table
QSqlQueryModel model = new QSqlQueryModel();

//Initializaton of the query
QSqlQuery *query = new QSqlQuery(dbm->db);

query->prepare("SELECT * FROM UserData");

if(query->exec())
{
model->setQuery(*query);
ui->tableView->setModel(model);

//The header delegate to paint a checkbox on the header
HeaderDelegate *myHeader = new HeaderDelegate(Qt::Horizontal, ui->tableView);
ui->tableView->setHorizontalHeader(myHeader);

int RowCount = model->rowCount();

qDebug() << RowCount;

CheckBoxDelegate *myCheckBoxDelegate = new CheckBoxDelegate();

for(int i = 0; i <model->rowCount(); i++)
{
ui->tableView->setItemDelegateForColumn(0,myCheckBoxDelegate);
}

ui->tableView->horizontalHeader()->setClickable(true);

ui->tableView->setSortingEnabled(true);
}

anda_skoa
28th January 2014, 13:14
You have two options:

- make your delegate create a QCheckBox in createEditor and also implement setEditorData and setModelData
- make the model return a value for Qt::CheckStateRole in column 0 instead of a value for Qt::DisplayRole. Might not even need a delegate in this case.

Cheers,
_

gfernandes
28th January 2014, 14:02
Do you have any example code that I could refer. I think the second method will not have a checkbox centered. I tried the following and it creates a normal checkbox, which is not centered. And here again I cannot check or uncheck. I am so confused.

QVariant CheckBoxSqlQueryModel::data( const QModelIndex &index, int role /*= Qt::DisplayRole*/ ) const
{
QVariant value = QSqlQueryModel::data(index,role);


if (role == Qt::CheckStateRole && index.column() == 0)
{
return (QSqlQueryModel::data(index).toInt() != 0) ? Qt::Checked : Qt::Unchecked;
}
return value;
}

Qt::ItemFlags CheckBoxSqlQueryModel::flags( const QModelIndex &index ) const
{
Qt::ItemFlags flags = QSqlQueryModel::flags(index);
if (index.column() == 0)
{
flags |= Qt::ItemIsUserCheckable;
flags |= Qt::ItemIsSelectable;
}
else
{
flags |= Qt::ItemIsEditable;
flags |= Qt::ItemIsSelectable;
}
return flags;
}

bool CheckBoxSqlQueryModel::setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole )
{
if (index.column() == 0)
{
role = Qt::CheckStateRole;
}
QSqlQueryModel::setData(index,value);
return true;
}

anda_skoa
28th January 2014, 17:55
What if you return QVariant() in column == 0 and role != Qt::CheckStateRole?

Or, if that does not center the checkbox, provide Qt::AlignCentered for Qt::AlignmentRole?

Cheers,
_