@mrjj Thanks, that works for my use case
Setting the data:
        if (node->value_category != TC_ASSIGNABLE_NONE) {
            QStandardItem *editorItem = new QStandardItem;
            QVariant v;
            AssignableData data(node);
            v.setValue(data);
            editorItem->setData(v, Qt::UserRole);
            //editorItem->setText(node->name);
            rowItems.append(editorItem);
        }
Setting editor data in the delegate:
void AssignableEditorDelegate::setEditorData(QWidget* editor, const QModelIndex &index) const {
    AssignableData data = qvariant_cast<AssignableData>(index.model()->data(index, Qt::UserRole));
    
    switch (data.m_valueCategory) {
        case TC_ASSIGNABLE_RANGE:
            switch (data.m_rangeInfo.range_data_type) {
                case TC_ASSIGNABLE_RANGE_INT: {
                    IntRangeEditor *ed = static_cast<IntRangeEditor*>(editor);
                    ed->setValue(data.value().toInt());
                    break;
                }
                default:
                    break;
            }
        default:
            break;
    }
}
Setting model data:
void AssignableEditorDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
    AssignableData data = qvariant_cast<AssignableData>(index.model()->data(index, Qt::UserRole));
    QVariant v;
    QStandardItemModel *s_model = static_cast<QStandardItemModel*>(model);
    
    switch (data.m_valueCategory) {
        ...
        case TC_ASSIGNABLE_RANGE:
            switch (data.m_rangeInfo.range_data_type) {
                case TC_ASSIGNABLE_RANGE_INT: {
                    IntRangeEditor *ed = static_cast<IntRangeEditor*>(editor);
                    data.setValue(ed->value());
                    v.setValue(data);
                    s_model->setData(index, v, Qt::UserRole);
                    s_model->setData(index, ed->value(), Qt::DisplayRole);
                    break;
                    }
                default:
                    break;
            }
        default:
            break;
    }
}
I also had to do setAutoFillBackground(true); in my editor widget to make the display text not overlap with the editor.