0

In my project, I have a QTreeView displaying items from a QStandardItemModel. Each item has data stored in several UserRoles.

QStandardItem* item = new QStandardItem();
item->setIcon(iconByte);
item->setData(3, Qt::UserRole+1);
item->setData(name, Qt::UserRole+2);
item->setData(data, Qt::UserRole+3);
... and so on

When the user double clicks on an item, a dialog with two line edits displays allowing the user to edit parts of the UserRole data. When editing ceases, the edits run through some logic and a display name is generated based on the new UserRole data.

However, this gets very tedious very quickly. With dialogs constantly popping up and whatnot, it's a slow and ugly solution.

I now would like to remove the dialog completely and show the line edit widgets WITHIN the item itself. By default, double clicking an item to edit it only shows one line edit widget to change the DISPLAY role. However I want two line edits to change the two USER roles. And then the normal logic continues.

How would I go about modifying the edit item portion of a QTreeView?

Thanks for your time!

mrg95
  • 2,371
  • 11
  • 46
  • 89
  • Utilizing a second column is not an option. The display text is not always two userrole data side by side. – mrg95 Dec 29 '16 at 06:02

1 Answers1

2

I would use a custom subclass of QStyledItemDelegate to solve this. Somewhere near your QTreeView you could have a QComboBox switching between the user roles; your custom delegate would somehow be informed which user role is currently selected and would intercept the method updating the data in the model to set the proper role.

An example implementation (not tested, may contain typos and errors):

class RoleSwitchingDelegate: public QStyledItemDelegate
{
public:
    explicit RoleSwitchingDelegate(QComboBox * roleSwitcher, QObject * parent = 0);

    virtual void setEditorData(QWidget * editor, const QModelIndex & index) const Q_DECL_OVERRIDE;
    virtual void setModelData(QWidget * editor, QAbstractItemModel * model,
               const QModelIndex & index) const Q_DECL_OVERRIDE;
private:
    QComboBox * m_roleSwitcher;
};

RoleSwitchingDelegate::RoleSwitchingDelegate(QComboBox * roleSwitcher, QObject * parent) :
    QItemDelegate(parent),
    m_roleSwitcher(roleSwitcher)
{}

void RoleSwitchingDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const
{
    // Assuming the model stores strings for both roles so that the editor is QLineEdit
    QLineEdit * lineEdit = qobject_cast<QLineEdit*>(editor);
    if (!lineEdit) {
        // Whoops, looks like the assumption is wrong, fallback to the default implementation
        QStyledItemDelegate::setEditorData(editor, index);
        return;
    }

    int role = m_roleSwitcher->currentIndex();
    QString data = index.model()->data(index, role).toString();
    lineEdit->setText(data);
}

void RoleSwitchingDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const
{
    // Again, assuming the model stores strings for both roles so that the editor is QLineEdit
    QLineEdit * lineEdit = qobject_cast<QLineEdit*>(editor);
    if (!lineEdit) {
        // Whoops, looks like the assumption is wrong, fallback to the default implementation
        QStyledItemDelegate::setModelData(editor, model, index);
        return;
    }

    int role = m_roleSwitcher->currentIndex();
    QString data = lineEdit->text();
    model->setData(index, data, role);
}

Once you have the delegate, you just need to set it to the view:

view->setItemDelegate(new RoleSwitchingDelegate(roleSwitchingComboBox, view));
Dmitry
  • 3,063
  • 2
  • 22
  • 32
  • I never heard of `QStyledItemDelegate`. I read up on the documentation a bit and looked over your answer. I don't think having to switch a QComboBox between roles is very user friendly. I really want to have 2 line edit widgets. Is it possible to pass a custom editor widget to setEditorData? – mrg95 Dec 29 '16 at 08:41
  • Yes, `QStyledItemDelegate` has `createEditor` method which returns a `QWidget` subclass. You can return different editors depending on the role. – Dmitry Dec 29 '16 at 08:43
  • Thanks for your help :D – mrg95 Dec 29 '16 at 08:59