QTableView displays boolean model as checkbox AND "true" or "false" text
-
Hi,
I have a model and a tableview. Table displays all model data. Data consists of a QVector of a struct. One member in struct is boolean. I can display it as checkbox in the table but there is a "true" or "false" text close to checkbox. If I doble-click on text, it converts to combobox. I don't know why.
What is the problem?Thanks.
#include "registermodel.h" #include <QFont> #include <QBrush> #include <QColor> #define DEB qDebug().noquote() << RegisterModel::RegisterModel(QObject *parent) : QAbstractTableModel(parent) { headers = QStringList(); headers << "Name" << "Page" << "Address" << "Current Value" << "Write Protect" << "Write Value"; } int RegisterModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return Registers.size(); } int RegisterModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return COLS; } QVariant RegisterModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole) { if (orientation == Qt::Horizontal) { return headers.at(section); } if (orientation == Qt::Vertical) { return section+1; } } return QVariant(); } void RegisterModel::setElement(int row, int col, QVariant value) { switch (col) { case 0: Registers[row].name = value.toString(); break; case 1: Registers[row].page = value.toUInt(); break; case 2: Registers[row].address = value.toUInt(); break; case 3: Registers[row].currValue = value.toUInt(); break; case 4: Registers[row].wrProtect = value.toBool(); break; case 5: Registers[row].wrValue = value.toUInt(); break; default: break; } } QVariant RegisterModel::data(const QModelIndex &index, int role) const { int row = index.row(); int col = index.column(); switch (role) { case Qt::DisplayRole: return getData(col, row); break; case Qt::EditRole: return getData(col, row); break; case Qt::TextAlignmentRole: if(col == 0) return Qt::AlignLeft; else return Qt::AlignRight; break; case Qt::CheckStateRole: if(col == 4) { if(Registers[row].wrProtect == true) { return Qt::Checked; } else { return Qt::Unchecked; } } break; case Qt::FontRole: if(col != 0) return QFont("Courier New", 10, QFont::Normal); break; case Qt::BackgroundRole: if(row % 2 == 0) { QColor c; c.setNamedColor("#E2E2E2"); QBrush bg(c); return bg; } break; default: return QVariant(); break; } return QVariant(); } bool RegisterModel::setData(const QModelIndex &index, const QVariant &value, int role) { if(role == Qt::EditRole) { setElement(index.row(), index.column(), value); } else if (role == Qt::CheckStateRole) { bool check = false; if((Qt::CheckState)value.toInt() == Qt::Checked) check = true; setElement(index.row(), index.column(), check); } emit dataChanged(index, index); return true; } Qt::ItemFlags RegisterModel::flags(const QModelIndex &index) const { int col = index.column(); if (col == 5) return Qt::ItemIsEnabled | Qt::ItemIsEditable | QAbstractTableModel::flags(index); else if (col == 4) return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsEditable | QAbstractTableModel::flags(index); else return QAbstractTableModel::flags(index); } void RegisterModel::changed(const int row) { emit dataChanged(index(row, 0), index(row, 5)); } bool RegisterModel::fillData(QVector<QStringList> *data) { Register reg; bool ok; beginInsertRows(QModelIndex(), 0, data->size()); for(int i = 0; i < data->size(); ++i) { reg.name = data->at(i).at(0); reg.address = data->at(i).at(2).toUInt(&ok, 16); reg.page = data->at(i).at(1).toUInt(&ok, 10); reg.currValue = 0; reg.wrProtect = true; reg.wrValue = 0; Registers.append(reg); } endInsertRows(); return true; } QVariant RegisterModel::getData(int col, int row) const { switch (col) { case 0: return QVariant(Registers[row].name); // QString break; case 1: return QVariant(Registers[row].page); // quint16 break; case 2: return QVariant(QString("%1").arg(Registers[row].address, 8, 16, QChar('0')).toUpper()); // quint32 break; case 3: return QVariant(QString("%1").arg(Registers[row].currValue, 8, 16, QChar('0')).toUpper()); // quint32 break; case 4: return QVariant(Registers[row].wrProtect); // bool break; case 5: return QVariant(QString("%1").arg(Registers[row].wrValue, 8, 16, QChar('0')).toUpper()); // quint32 break; default: return QVariant(); break; } } void RegisterModel::dumpRegisters() { DEB "+--------------------------------------------------------------------------------+"; DEB QString("| %1%2%3: %4 %5 %6 |").arg("Name", -25). \ arg("Page", 5).\ arg("Address", 11).\ arg("Curr Val.", 10).\ arg("Wr Protect", 12). \ arg("Wr Value", 8); foreach (Register reg, Registers) { QString name = reg.name.left(23) + ((reg.name.size() > 23) ? ".." : ""); DEB QString("| %1%2 %3: %4 %5 %6 |").arg(name, -25). \ arg(reg.page, 5).\ arg(reg.address, 8, 16, QChar('0')).\ arg(reg.currValue, 8, 16, QChar('0')).\ arg(reg.wrProtect, 12). \ arg(reg.wrValue, 8, 16, QChar('0')); } DEB "+--------------------------------------------------------------------------------+"; }
-
You return a Qt::DisplayRole and EditRole for row 4 also - so the view displays this data.
-
Ok, I changed it but now it displays an editable field. When I double-click it opens a text field. When I leave the text field empty, checkbox gets false. Checkbox alone works correctly, it changes datamodel.
registermodel.cpp:
..... case Qt::DisplayRole: if(col != 4) return getData(col, row); break; case Qt::EditRole: if(col != 4) return getData(col, row); break; .....
-
You have to return the correct flags for this column with http://doc.qt.io/qt-5/qabstractitemmodel.html#flags - Qt::ItemIsUserCheckable but not Qt::ItemIsEditable iirc
-
Ok, thanks. It displays only checkbox now.