how can i Polutate table Widget with combo Box and spinBox delegates - qcombobox

How can i have different delegates in different columns of a table. for instance, i want spinbox delegate in 1st column and combobox in 2nd column.
i took an example of spinbox delegate from examples directories and tried to do the changes:
main.cpp
#include "test1.h"
#include <QApplication>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QTableWidget>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QStandardItemModel model(4, 2);
QTableView tableView;
tableView.setModel(&model);
SpinBoxDelegate sdelegate;
ComboBoxDelegate comDel;
tableView.setItemDelegate(&sdelegate);
tableView.horizontalHeader()->setStretchLastSection(true);
for (int row = 0; row < 4; ++row)
{
for (int column = 0; column < 1; ++column)
{
tableView.setItemDelegate(&comDel);
QModelIndex index = model.index(0, 0, QModelIndex());
}
for (int column = 1; column < 2; ++column)
{
tableView.setItemDelegate(&sdelegate);
QModelIndex index = model.index(1, 1, QModelIndex());
}
}
tableView.setWindowTitle(QObject::tr("Spin Box & combo Box Delegate"));
tableView.show();
return app.exec();
}
test1.h my header file
#ifndef LINEEDIT_H
#define LINEEDIT_H
#include <QStyledItemDelegate>
class SpinBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
SpinBoxDelegate(QObject *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) /*const Q_DECL_OVERRIDE*/;
void setEditorData(QWidget *editor, const QModelIndex &index) /*const Q_DECL_OVERRIDE*/;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) /*const Q_DECL_OVERRIDE*/;
void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &index) /*const Q_DECL_OVERRIDE*/;
};
class ComboBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
ComboBoxDelegate(QObject *parent = 0);
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;
};
#endif // LINEEDIT_H
test1.cpp my cpp file
#include "test1.h"
#include <QSpinBox>
#include <QComboBox>
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */)/* const*/
{
QSpinBox *editor = new QSpinBox(parent);
editor->setFrame(false);
editor->setMinimum(0);
editor->setMaximum(100);
return editor;
}
void SpinBoxDelegate::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);
}
void SpinBoxDelegate::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);
}
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/* index */) /*const*/
{
editor->setGeometry(option.rect);
}
ComboBoxDelegate::ComboBoxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
QWidget *ComboBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */) const
{
QComboBox *editor = new QComboBox(parent);
//QStringList list ;
//list << "srikanth" << "dilip";
//editor->addItems(list);
editor->installEventFilter(const_cast<ComboBoxDelegate*>(this));
return editor;
}
void ComboBoxDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
QString value = index.model()->data(index, Qt::DisplayRole).toString();
QComboBox *comboBox = static_cast<QComboBox*>(editor);
comboBox->addItem(value);
}
void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
QString value = comboBox->currentText();
model->setData(index, value);
}
void ComboBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}

Related

QStyledItemDelegate does not show desired Widget in the cells of QTableView

I want to test how to put QSpinBox into cells of QTableView in Qt 6.2.2, but the delegate does not appear to work, which means it does not show QSpinBox in the cells, and I've tested the delegate member functions by qDebug which reveals that none of these functions work! could anyone help to fix the problem? Many thanks in advance!
Below is the code:
testtabledelegate.h
#ifndef TESTTABLEDELEGATE_H
#define TESTTABLEDELEGATE_H
#include <QStyledItemDelegate>
#include <QWidget>
class TestTableDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
TestTableDelegate(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;
private:
};
#endif // TESTTABLEDELEGATE_H
testtabledelegate.cpp
#include "testtabledelegate.h"
#include <QSpinBox>
TestTableDelegate::TestTableDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
}
QWidget *TestTableDelegate ::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
qDebug() << "Draw Control";
Q_UNUSED(option);
Q_UNUSED(index);
QSpinBox *editor = new QSpinBox(parent);
editor->setFrame(false);
editor->setMinimum(0);
editor->setMaximum(10000);
return editor;
}
void TestTableDelegate ::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);
}
void TestTableDelegate ::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);
}
void TestTableDelegate ::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
editor->setGeometry(option.rect);
}
testtablemodel.h
#ifndef TESTTABLEMODEL_H
#define TESTTABLEMODEL_H
#include <QAbstractTableModel>
class TestTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit TestTableModel(QObject *parent = nullptr);
protected:
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QVariant data(const QModelIndex &index, int role) const;
private:
//QStringList *testList = QStringList() << "R1" << "R2" << "R3" << "R4" << "R5";
};
#endif // TESTTABLEMODEL_H
testtablemodel.cpp
#include "testtablemodel.h"
TestTableModel::TestTableModel(QObject *parent) : QAbstractTableModel(parent)
{
}
int TestTableModel::rowCount(const QModelIndex &parent) const
{
return 5;
}
int TestTableModel::columnCount(const QModelIndex &parent) const
{
return 5;
}
QVariant TestTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole)
{
if (orientation == Qt::Horizontal)
return QStringLiteral("Field %1").arg(section);
else if (orientation == Qt::Vertical)
return section + 1;
else
return(QVariant());
}
else
return(QVariant());
}
QVariant TestTableModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
{
return index.row();
}
else if (role == Qt::TextAlignmentRole)
{
return Qt::AlignCenter;
}
else
{
return QVariant();
}
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
//#include "testtableheader.h"
#include "testtablemodel.h"
#include "testtabledelegate.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
TestTableModel *testModel = new TestTableModel();
TestTableDelegate *testDelegate = new TestTableDelegate(this);
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTableView>
#include <QStyledItemDelegate>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->tableView->setAlternatingRowColors(true);
ui->tableView->setModel(testModel);
ui->tableView->setItemDelegate(testDelegate);
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

Access data from Tree Model item

This is my Table View structure.
How can i browse through the Table view and get SubChild as a TreeItem element.
For Example -> Group2$Child2$SubChild.
This line should return back subchild as TreeItem*.
The Header file for the TreeModel.
#pragma once
#include <QAbstractItemModel>
#include <QString>
#include <QMimedata.h>
#include <Qdatastream.h>
#include "Container.h"
class TreeItem;
class TreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
TreeModel( const QString &header, const Container &data, QObject *parent
= 0);
~TreeModel();
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role =
Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role =
Qt::EditRole) override;
bool setHeaderData(int section, Qt::Orientation orientation,
const QVariant &value, int role = Qt::EditRole) override;
QModelIndex index(int row, int column, const QModelIndex &parent) const
override;
QModelIndex parent(const QModelIndex &parent) const override;
bool insertRows(int position, int rows, const QModelIndex &parent);
// bool removeRows(int position, int rows, const QModelIndex &parent =
QModelIndex()) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const
override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Container GetContainer(const QModelIndex &index);
void SetContainer(const QModelIndex &index, Container cont);
////////////////////// Drag And Drop Actions ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Qt::DropActions supportedDropActions() const override;
Qt::DropActions supportedDragActions() const override;
QStringList mimeTypes() const override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
void setupModelData(const QStringList &lines, TreeItem *parent);
void removeItem(TreeItem *item);
TreeItem *getItem(const QModelIndex &index) const;
TreeItem *getRoot();
private:
TreeItem *rootItem;
};
I would be happy to post any specific code required.

How to set icon center in QTableView?

NetworkPageForm::NetworkPageForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::NetworkPageForm),
devicesModel(NULL)
{
ui->setupUi(this);
devicesModel = new QStandardItemModel(0, 4, parent);
devicesModel->setHeaderData(0, Qt::Horizontal, QObject::tr("IP"));
devicesModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
devicesModel->setHeaderData(2, Qt::Horizontal, QObject::tr("Last Online"));
devicesModel->setHeaderData(3, Qt::Horizontal, QObject::tr("Status"));
ui->devicesTableView->setModel(devicesModel);
ui->devicesTableView->resizeColumnsToContents();
}
void NetworkPageForm::addDevice(const QString &ip, int device_type) {
bool haveSameItem = false;
for(int i=0; i<devicesModel->rowCount(); i++) {
QStandardItem * ipItem = devicesModel->item(i, 0);
QStandardItem * nameItem = devicesModel->item(i, 1);
if(QString::compare(ipItem->text(), ip)== 0 && QString::compare(nameItem->text(), deviceStr)==0) {
devicesModel->setData(devicesModel->index(i, 2), BaseModel::now());
haveSameItem = true;
}
}
if(!haveSameItem)
{
int last = devicesModel->rowCount();
devicesModel->insertRow(last);
devicesModel->setData(devicesModel->index(last, 0), ip);
devicesModel->setData(devicesModel->index(last, 1), device_type);
devicesModel->setData(devicesModel->index(last, 2), BaseModel::now());
devicesModel->setData(devicesModel->index(last, 3), QIcon(":/res/images/online_icon.png"), Qt::DecorationRole);
// This function does not work, the icon is algin left.
// devicesModel->item(last, 3)->setTextAlignment(Qt::AlignCenter);
}
ui->devicesTableView->resizeColumnsToContents();
}
Is there a way to set QIcon item center in QTableView?
Update:
I create my own QStyledItemDelegate sub class as #RazrFalcon answered.
#include <QStyledItemDelegate>
class MyDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
MyDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {}
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;
private slots:
};
void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
if(index.column() == 3) {
// TODO
} else {
QStyledItemDelegate::paint(painter, option, index);
}
}
QSize MyDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const {
if(index.column() == 3) {
// TODO
} else {
return QStyledItemDelegate::sizeHint(option, index);
}
}
void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
QStyledItemDelegate::setModelData(editor, model, index);
}
And set ui->devicesTableView->setItemDelegate(new MyDelegate);
Could someone help me how to set icon column center in QTableView?
There is no default way. You should implement your own QStyledItemDelegate.
UPD: example added
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_ASSERT(index.isValid());
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
// disable default icon
opt.icon = QIcon();
// draw default item
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0);
const QRect r = option.rect;
// get pixmap
QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
QPixmap pix = icon.pixmap(r.size());
// draw pixmap at center of item
const QPoint p = QPoint((r.width() - pix.width())/2, (r.height() - pix.height())/2);
painter->drawPixmap(r.topLeft() + p, pix);
}
It's no need to do it in delegate. The delegate will make your style sheet unavailable.
You can paint the icon in the middle of a rectangle pixmap which is as same size as the cell, and return it in the QAbstractItemModel::data() function with Qt::DecorationRole. Like this:
Qt::DecoratoinRole:
QPixmap pixmap(w, h); //w=cell width, h=cell
pixmap.fill(Qt::transparent); // draw a transparent rectangle
QPixmap iconPixmap(":/xx.png");
QPainter painter(&pixmap);
//Calculate the center coordinate x,y for iconPixmap
painter.draw(x, y, iconWidth, iconHeight, iconPixmap);
return pixmap;

Access pointer to QWidget(Combobox) of the customdelegate

I have derived a class from QStyledItemDelegate. I am using a QComboBox in this delegate. This delegate is used in QTableView.
My question is, how can i change the index of the Combobox in the delegate programatically i.e how to access the pointer to that widget outside the delegate class ?
I have checked that CreateEditor, SetEditorData, SetModelData functions (of QStyledItemDelegate) are called automatically when we click on the combobox and we cannot call them manually to maniplate the data in the model.
afaik any time you start editing and the combobox is shown, it will allocate a new one. if you want to have a permanent combobox, you should look at
QTableView::setIndexWidget(const QModelIndex&, QWidget*)
so you could access the combobox with the following code:
const QMoodelIndex idx = model->index(row, column);
QWidget* wid = view->indexWidget(idx);
QComboBox* box = qobject_cast<QComboBox*>(wid);
if (box)
// do your thing
You can have the contents of your combobox as a class member of your delegate in a QStringList. Your item delegate can be like :
#include <QStyledItemDelegate>
#include <QComboBox>
class ComboBoxDelegate: public QStyledItemDelegate
{
Q_OBJECT
public:
ComboBoxDelegate(QObject *parent = 0);
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;
QStringList comboItems;
mutable QComboBox *combo;
private slots:
void setData(int val);
};
ComboBoxDelegate::ComboBoxDelegate(QObject *parent ):QStyledItemDelegate(parent)
{
}
QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
combo = new QComboBox( parent );
QObject::connect(combo,SIGNAL(currentIndexChanged(int)),this,SLOT(setData(int)));
combo->addItems(comboItems);
combo->setMaxVisibleItems(comboItems.count());
return combo;
}
void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QString text = index.model()->data( index, Qt::DisplayRole ).toString();
int comboIndex = comboItems.indexOf(QRegExp(text));
if(comboIndex>=0)
(static_cast<QComboBox*>( editor ))->setCurrentIndex(comboIndex);
}
void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
model->setData( index, static_cast<QComboBox*>( editor )->currentText() );
}
void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry( option.rect );
}
void ComboBoxDelegate::setData(int val)
{
emit commitData(combo);
//emit closeEditor(combo);
}
When you want to update the items in combobox somewhere in your code just get a pointer to the item delegate by calling itemDelegateForColumn and access the comboItems member :
ComboBoxDelegate * itemDelegate = qobject_cast<ComboBoxDelegate *>(ui->tableView->itemDelegateForColumn(columnIndex));
//Updating combobox items
itemDelegate->comboItems.append("newItem");
...

QStandardItem + QComboBox

I am trying to put a QComboBox into a QStandardItem to be used in a QStandardItemModel. I have been looking around and I cannot find an answer, any ideas?
You don't store a QComboBox in a QStandardItemModel. Let's say you have the following choices:
A
B
C
D
and you have a list with two items in a QListView, the first value being A the second being D:
QListView* pView = new QListView();
QStandardItemModel* pModel = new QStandardItemModel();
pView->setModel(pModel);
pModel->appendRow(new QStandardItem("A"));
pModel->appendRow(new QStandardItem("D"));
What we created above is a list widget which will display the values of "A" and "D". Now, to the QComboBox. I assume you want that to edit the values of "A" and "D" in the list. For this, you need to create a QItemDelegate.
See http://doc.qt.io/qt-4.8/qitemdelegate.html
An attempt:
class ComboBoxDelegate : public QItemDelegate
{
Q_OBJECT
public:
ComboBoxDelegate(QObject *parent = 0);
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;
};
ComboBoxDelegate::ComboBoxDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
QWidget *ComboBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */) const
{
QComboBox *editor = new QComboBox(parent);
editor->addItem("A");
editor->addItem("B");
editor->addItem("C");
editor->addItem("D");
return editor;
}
void ComboBoxDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
QString value = index.model()->data(index, Qt::EditRole).toString();
QComboBox *cBox = static_cast<QComboBox*>(editor);
cBox->setCurrentIndex(cBox->findText(value));
}
void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QComboBox *cBox = static_cast<QComboBox*>(editor);
QString value = cBox->currentText();
model->setData(index, value, Qt::EditRole);
}
void ComboBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
And then you need to set the delegate on the QListView to make it work, see:
pView->setItemDelegate(new ComboBoxDelegate(pView));

Resources