PDA

View Full Version : Editing of Cell in QTableView with QComboBox as Editor



apatwork
6th December 2017, 15:11
Hi there,

I can't get an editor for a cell in a table working. The table is displayed in a QTableView with a model implemented in a subclass of QAbstractTableModel. One column is to display a pen width parameter. This pen width is configured using a wizard. In the wizard a combo box is used which looks as follows:

12713

The code for the model that is used by the combo box I found somewhere
in the internet (and adapted it for my purposes). It looks as follows:

Model class declaration:



class PenWidthModel : public QAbstractListModel {

public:
PenWidthModel(QObject *parent = nullptr);

public:
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;

private:
static void initialize();

static std::unique_ptr<QMap<int, QIcon>> thePenWidths2Icons;
};


Model class implementation:



unique_ptr<QMap<int, QIcon>>
PenWidthModel::thePenWidths2Icons(nullptr);

PenWidthModel::PenWidthModel(QObject *parent) :
QAbstractListModel(parent) {
if (thePenWidths2Icons.get() != nullptr) {
return;
}
PenWidthModel::initialize();
}

int PenWidthModel::rowCount(const QModelIndex &parent) const {
if (parent.isValid())
return 0;

return 5;
}

QVariant PenWidthModel::data(const QModelIndex &index, int role) const {
if (role == Qt::DecorationRole) {
return (*thePenWidths2Icons)[index.row()];
}
return QVariant();
}

void PenWidthModel::initialize() {
thePenWidths2Icons = make_unique<QMap<int, QIcon>>();
for (int i = 0; i < 6; ++i) {
QPixmap pix(80, 14);
pix.fill(Qt::white);

QBrush brush(Qt::black);
QPen pen(brush, static_cast<double>(i + 1), Qt::SolidLine);

QPainter painter(&pix);
painter.setPen(pen);
painter.drawLine(2,7,78,7);
painter.end();
thePenWidths2Icons->insert(i, QIcon(pix));
}
}


As can be seen in the code for each of the available pen widths a QIcon object showing a pixmap with a line of appropriate thickness is provided (thickness of 0 is avoided).
This model works fine in conjunction with the wizard and the combo box used in it for selection of a pen width.

The pen width configured for a graph is later on shown in a table of graphs with their properties. In this table I want to be able to edit the pen width for a certain graph. In this context I want to reuse the PenWidthModel class. From my current understanding to edit data in a table in a non-standard way one has to use so called item delegates. So I implemented an item delegate that uses a QComboBox for editing of the pen width. My code looks as follows:

Item delegate class declaration:



class PenWidthDelegate : public QStyledItemDelegate {
public:
PenWidthDelegate(QObject *parent);

~PenWidthDelegate();

public:
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
};


Item delegate class implementation:



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

PenWidthDelegate::~PenWidthDelegate() {
}

QWidget *PenWidthDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const {
QComboBox *penWidthCB = new QComboBox(parent);
penWidthCB->setModel(new PenWidthModel(parent));
return penWidthCB;
}

void PenWidthDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
QComboBox *penWidthCB = static_cast<QComboBox*>(editor);
penWidthCB->setCurrentIndex(index.model()->data(index, Qt::EditRole).toInt());
}

void PenWidthDelegate::setModelData(QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index) const {
QComboBox *penWidthCB = static_cast<QComboBox*>(editor);
int ix = penWidthCB->currentIndex();
model->setData(index, ix, Qt::EditRole);
}


As can be seen in the code in the createEditor(...) method I create the QComboBox instance to be used and assign an instance of the PenWidthModel class as its model. In the setEditorData(...) method I set the index of the to be shown pen width icon. and in the setModelData(...) method I write the selected pen width back to the table's model. But unfortunately the combo box shown when I initiate editing of a pen width does not display the icons representing the different pen widths. Instead it looks as follows:

12714

Obviously the icons provided by the model class are not displayed. Additionally the result of an edit is not immediately shown but seems to be shown only after one has clicked somewhere besides the edited cell.

Obviously I'm doing something wrong ...
Any help would be highly appreciated.

high_flyer
8th December 2017, 10:39
Obviously the icons provided by the model class are not displayed.
Its hard to tell from the posted screenshots, but to me it DOES seems to show the icons with the various line widths albeit it seems the margins of the content are thicker (so the icons seem to be "squashed", but I see the lines so maybe I don't understand what you mean?
Could you try to elaborate on what you see vs. what you expect?