Unsolved How to insert/remove row into QTableView?
-
Hi, guys!
I am using a QTableView to display some QWidgets for input. The first column is a QCheckBox, and the second to the fouth are all QComboBox.
To make it, I use a class derived from QAbstractTableModel and a class derived from QStyledItemDelegate.
The code of QAbstractTableModel is as below:class FormulaListModel : public QAbstractTableModel { typedef struct { int op1; int op2; int op; bool isEnable; }FORMULA, *PFORMULA; Q_OBJECT public: FormulaListModel(QObject *parent); ~FormulaListModel(); /*Implement the necessary virtual function of QAbstractListModel*/ int rowCount(const QModelIndex & parent = QModelIndex()) const; int columnCount(const QModelIndex & parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole); void AddDevName(QString name);//device names void AddOperator(QString name);//operators void AddFormula(int op1, int op2, int op, bool isEnable);//add formula private: QVector<PFORMULA> m_lsFormula; QStringList m_lsDevNames; QStringList m_lsOperators; }; FormulaListModel::FormulaListModel(QObject *parent) : QAbstractTableModel(parent) { } FormulaListModel::~FormulaListModel() { foreach(PFORMULA f, m_lsFormula) { if (f) { delete f; } } m_lsFormula.clear(); m_lsDevNames.clear(); m_lsOperators.clear(); } int FormulaListModel::rowCount(const QModelIndex & parent) const { return m_lsFormula.count(); } int FormulaListModel::columnCount(const QModelIndex & parent) const { return 4; } QVariant FormulaListModel::data(const QModelIndex & index, int role) const { switch(role) { case Qt::EditRole: { int r = index.row(); int c = index.column(); PFORMULA pf = m_lsFormula[r]; switch(c) { case 0: return pf->isEnable; case 1: return m_lsDevNames[pf->op1]; case 2: return m_lsOperators[pf->op]; case 3: return m_lsDevNames[pf->op2]; } } case Qt::DisplayRole: { int c = index.column(); switch(c) { case 0: return "Use"; case 1: case 3: return m_lsDevNames; case 2: return m_lsOperators; } } case Qt::DecorationRole: { QColor clr(Qt::transparent); return clr; } case Qt::SizeHintRole: return QSize(130, 16); case Qt::FontRole: { QFont font; font.setBold(true); return font; } case Qt::BackgroundRole: { QBrush brush(Qt::transparent); return brush; } case Qt::TextAlignmentRole: { return Qt::AlignHCenter; } case Qt::CheckStateRole: { return Qt::Checked; } case Qt::TextColorRole: { QColor clr(Qt::black); return clr; } case Qt::ToolTipRole: { return "Formula"; } default: return QVariant(); } } bool FormulaListModel::setData(const QModelIndex & index, const QVariant & value, int role) { QModelIndex tl, rb; tl = createIndex(0, 0); rb = createIndex(m_lsFormula.count(), 3); emit dataChanged(tl, rb); return true; } void FormulaListModel::AddDevName(QString name) { m_lsDevNames << name; } void FormulaListModel::AddOperator(QString name) { m_lsOperators << name; } void FormulaListModel::AddFormula(int op1, int op2, int op, bool isEnable) { beginResetModel(); PFORMULA pf = new FORMULA; pf->op = op; pf->op1 = op1; pf->op2 = op2; pf->isEnable = isEnable; m_lsFormula << pf; endResetModel(); }
Code of QStyledItemDelegate is as below:
class CheckBoxDelegate : public QStyledItemDelegate { Q_OBJECT public: CheckBoxDelegate(QObject *parent); ~CheckBoxDelegate(); QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index)const; void setEditorData(QWidget * editor, const QModelIndex & index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const; void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; protected: bool eventFilter ( QObject * editor, QEvent * event ); private: }; CheckBoxDelegate::CheckBoxDelegate(QObject *parent) : QStyledItemDelegate(parent) { } CheckBoxDelegate::~CheckBoxDelegate() { } QWidget * CheckBoxDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index)const { QVariant value = index.model()->data(index, Qt::DisplayRole); if (index.column() == 0) { QCheckBox * pBox = new QCheckBox(parent); pBox->setText(value.toString()); return pBox; } else { QComboBox * pBox = new QComboBox(parent); pBox->addItems(value.toStringList()); return pBox; } } void CheckBoxDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const { QVariant value = index.model()->data(index, Qt::EditRole); if (index.column() == 0) { bool checked = value.toBool(); QCheckBox * pBox = static_cast<QCheckBox *>(editor); if (pBox) { pBox->setChecked(checked); } } else { QString str = index.model()->data(index, Qt::EditRole).toString(); //qDebug() << index << str; QComboBox * pBox = static_cast<QComboBox *>(editor); if (pBox) { pBox->setCurrentIndex(pBox->findText(str)); } } } void CheckBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { QRect rc = option.rect; editor->setGeometry(rc); } void CheckBoxDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const { if (index.column() == 0) { QCheckBox * pBox = static_cast<QCheckBox *>(editor); pBox->update(); bool checked = pBox->isChecked(); model->setData(index, checked, Qt::EditRole); } else { QComboBox * pBox = static_cast<QComboBox *>(editor); pBox->update(); QString str = pBox->currentText(); model->setData(index, str, Qt::EditRole); } } void CheckBoxDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { int x = option.rect.x(); int y = option.rect.y(); QVariant value = index.model()->data(index, Qt::DisplayRole); if (index.column() == 0) { bool checked = value.toBool(); QStyleOptionButton style; style.rect = QRect(x, y + 8, 12, 12); style.state |= QStyle::State_Enabled; style.state |= checked ? QStyle::State_On : QStyle::State_Off; QApplication::style()->drawControl(QStyle::CE_CheckBox, &style, painter); } else { QStyleOptionComplex style; style.rect = QRect(x, y + 8, 12, 12); style.state = QStyle::State_HasFocus; style.state |= QStyle::State_Enabled; QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &style, painter); } } bool CheckBoxDelegate::eventFilter ( QObject * editor, QEvent * event ) { if (event->type() == QEvent::Wheel) { QString clsName = editor->metaObject()->className(); if (clsName.compare("QCheckBox") == 0) { QObject * obj = editor->parent(); while(obj) { qDebug() << obj; obj = obj->parent(); } return true; } qDebug() << editor; } //qDebug() << event->type() << editor; return QStyledItemDelegate::eventFilter(editor, event); }
The code snippet to initialize QTabview is as below:
m_pModel2 = new FormulaListModel(this); ui.lvContainer->setModel(m_pModel2); ui.lvContainer->setShowGrid(false); QHeaderView * pHeader = ui.lvContainer->horizontalHeader(); pHeader->hide(); pHeader = ui.lvContainer->verticalHeader(); pHeader->hide(); ui.lvContainer->setColumnWidth(0, 80); ui.lvContainer->setColumnWidth(1, 150); ui.lvContainer->setColumnWidth(2, 150); ui.lvContainer->setColumnWidth(3, 150); ui.lvContainer->setItemDelegate(new CheckBoxDelegate(this)); for (int i = 0;i < m_pModel2->rowCount();i ++) { ui.lvContainer->openPersistentEditor(m_pModel2->index(i, 0)); ui.lvContainer->openPersistentEditor(m_pModel2->index(i, 1)); ui.lvContainer->openPersistentEditor(m_pModel2->index(i, 2)); ui.lvContainer->openPersistentEditor(m_pModel2->index(i, 3)); } ui.lvContainer->updateGeometry();
Code snippet to insert row is as below:
m_pModel2->AddDevName("dev1"); m_pModel2->AddDevName("dev2"); m_pModel2->AddOperator("+"); m_pModel2->AddOperator("-"); m_pModel2->AddFormula(0, 0, 0, false);
When I execute these code, only a empty QCheckBox with a equal symbol is display. The text and other QComboBox doesn't appear.
I am a freshman of Qt. I don't know how to make it work well. Please help me with kind. Thx! -
Part of problem had been resolved. I use the following code to add item:
m_pModel2->AddFormula(1, 1, 0, false); for (int i = 0;i < m_pModel2->rowCount();i ++) { ui.lvContainer->openPersistentEditor(m_pModel2->index(i, 0)); ui.lvContainer->openPersistentEditor(m_pModel2->index(i, 1)); ui.lvContainer->openPersistentEditor(m_pModel2->index(i, 2)); ui.lvContainer->openPersistentEditor(m_pModel2->index(i, 3)); }
And the item can be displayed as I wanted. But another problem is still exist: after I add a new item, the text I had selected for QComboBox is lost. How to reserve them till I finish the operation?