Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QTableView combo box delegate



  • The effect i wanna achieve is, instead of creating the combo-box, changing the index, then applying the data to the table view, i would like the combo box to disappear when the index is changed.

    Because the functions are const, i can't use a signal there, i don't know much how to get the pointer of the new created combo box and use a signal, since it's const and local, can't add any return to it, can't add additional parameters, because i don't know where the functions are called and by what they are called, can't do much. Need some help with it.

    QWidget *Combo_Box_Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QComboBox* combo_box = new QComboBox(parent);
    
        for(int i = 0; i < this->labels.count(); i++)
        {
            combo_box->addItem(this->labels[i]);
        }
        return combo_box;
    }
    
    void setEditorData(QWidget *editor, const QModelIndex &index) const
    {
        int value = 0;
        QString text = index.model()->data(index, Qt::EditRole).toString();
        QComboBox* combo_box = static_cast<QComboBox*>(editor);
    
        for(int i = 0; i < this->labels.count(); i++)
        {
            if(text == this->labels[i]){value = i; break;}
        }
        combo_box->setCurrentIndex(value);
    }
    
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
    {
        QComboBox* combo_box = static_cast<QComboBox*>(editor);
        model->setData(index, combo_box->currentText(), Qt::EditRole);
    }
    
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        editor->setGeometry(option.rect);
    }
    

    From what i tested, to get the combo box disappear, the setModelData should be called right after i change the index, for the first time, not after the user click somewhere.



  • add connect(combo_box , QOverload<int>::of(&QComboBox::currentIndexChanged), this, std::bind(&QAbstractItemDelegate::commitData,this,combo_box)); as the last line of Combo_Box_Delegate::setEditorData



  • @VRonin said in QTableView combo box delegate:

    std::bind

    It deosn't compile. There are few more warnings to this error.

    'const QAbstractItemDelegate*' to 'QAbstractItemDelegate*' [-fpermissive]
    { return ((__ptr)._M_pmf)(std::forward<_Args>(__args)...); }
    ^

    'static typename QtPrivate::QEnableIf<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == (-1)), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType) [with Func1 = void (QComboBox::)(int); Func2 = std::_Bind<std::_Mem_fn<void (QAbstractItemDelegate::)(QWidget*)>(const Combo_Box_Delegate*, QComboBox*)>; typename QtPrivate::QEnableIf<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == (-1)), QMetaObject::Connection>::Type = QMetaObject::Connection; typename QtPrivate::FunctionPointer<Func>::Object = QComboBox]'



  • const always gets me!

    connect(combo_box , QOverload<int>::of(&QComboBox::currentIndexChanged), this, std::bind(&QAbstractItemDelegate::commitData,const_cast<QAbstractItemDelegate*>(this),combo_box));

    And yes, it's safe, don't worry.



  • @VRonin Another problem.

    'const Combo_Box_Delegate*' to type 'QAbstractItemDelegate*'
    connect(combo_box , QOverload<int>::of(&QComboBox::currentIndexChanged), this, std::bind(&QAbstractItemDelegate::commitData, const_cast<QAbstractItemDelegate*>(this), combo_box));
    ^

    Combo_Box_Delegate it's a custom class, just to inherit the data, and change it. To what type should i cast it to?



  • Tested and working:

    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const Q_DECL_OVERRIDE
        {
            QComboBox* combo_box = new QComboBox(parent);
    
            for(int i = 0; i < labels.count(); i++)
            {
                combo_box->addItem(labels[i]);
            }
            return combo_box;
        }
        void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE
        {
            int value = 0;
            QString text = index.model()->data(index, Qt::EditRole).toString();
            QComboBox* combo_box = static_cast<QComboBox*>(editor);
    
            for(int i = 0; i < this->labels.count(); i++)
            {
                if(text == this->labels[i]){value = i; break;}
            }
            combo_box->setCurrentIndex(value);
            connect(combo_box , QOverload<int>::of(&QComboBox::currentIndexChanged), this, std::bind(&QAbstractItemDelegate::commitData,const_cast<Combo_Box_Delegate*>(this),combo_box));
        }
        void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE
        {
            QComboBox* combo_box = static_cast<QComboBox*>(editor);
            model->setData(index, combo_box->currentText(), Qt::EditRole);
        }
    
        void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const Q_DECL_OVERRIDE
        {
            editor->setGeometry(option.rect);
        }
    


  • @VRonin said in QTableView combo box delegate:

    Q_DECL_OVERRIDE

    I had to move the definition to the header, otherwise the macro gives me compile errors, when i did it, it compiles, but the combo box don't disappears after first change and i still need to click somewhere to apply the data.


Log in to reply