QTreeView with QItemDelegate and QComboBox inside not work propertly



  • Hi guys,

    I have a problem with the QItemDelegate because my QTreeView need to click over the QComboBox cell one time for enter in edit mode and other time to expand the QComboBox. I need that this firts click expand the QComboBox.

    I try with the edit trigers of the QTreeView but it work similar, I need that when click one first time enter in edit mode.

    It is posible to enter in edit modo when mouse over the cell with combobox and them the first click expand the QComboBox?

    I have already try with comboBox->showPopup(); in the setEditorData of QItemDelegate but it not work fine.

    Please can anyone help me?



  • For me it is working with showPopup(). Difficult to guess whats wrong in your situation. Do you have some minimal code?



  • Hi, i will try to explain my situation. I have a QTreeView.

    @
    m_table = new QTreeView(this);
    m_table->setEditTriggers(QAbstractItemView::AllEditTriggers);
    m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_table->setSelectionMode(QAbstractItemView::SingleSelection);
    m_table->setDragEnabled(false);
    m_table->setAllColumnsShowFocus(true);
    m_table->setAlternatingRowColors(false);
    m_table->setRootIsDecorated(false);
    m_table->setItemsExpandable(false);
    m_table->setSortingEnabled(false);
    m_table->header()->setClickable(false);
    m_table->header()->setStretchLastSection(false);
    m_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    m_model = new MyItemModel(m_table);
    m_table->setModel(m_model);

    m_selectionModel = new QItemSelectionModel(m_model);
    m_table->setSelectionModel(m_selectionModel);

    m_delegate = new MyDelegate(
    m_table);

    m_table->header()->setResizeMode(0, QHeaderView::Stretch);
    m_table->header()->resizeSection(1, 135);
    m_table->header()->resizeSection(2, 135);
    m_table->header()->resizeSection(3, 60);

    m_table->setItemDelegateForColumn(1, m_delegate);
    m_table->setItemDelegateForColumn(2, m_delegate);
    m_table->setItemDelegateForColumn(3, m_delegate);
    @

    The delegate is responsible for managing the drop-down is as follows.

    @
    void MyItemDelegate::paint(QPainter *painter,
    const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
    if ((index.column() == 1) || (index.column() == 2))
    {
    QStyleOptionComboBox comboBoxOption;
    comboBoxOption.rect = option.rect;
    comboBoxOption.state = QStyle::State_Active; // | QStyle::State_Enabled;
    comboBoxOption.currentText = index.model()->data(index).toString();
    QApplication::style()->drawComplexControl(QStyle::CC_ComboBox,
    &comboBoxOption, painter);
    QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel,
    &comboBoxOption, painter);
    }
    else if (index.column() == 3)
    {
    QStyleOptionButton buttonOption;
    buttonOption.rect = option.rect;
    buttonOption.state = QStyle::State_Active; // | QStyle::State_Enabled;
    buttonOption.text = index.model()->data(index).toString();
    QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption,
    painter);
    }
    else
    {
    QItemDelegate::paint(painter, option, index);
    }

    }

    QWidget* MyItemDelegate::createEditor(QWidget parent,
    const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
    if ((index.column() == 1) || (index.column() == 2))
    {
    QComboBox
    comboStatus = new QComboBox(parent);

        return comboStatus;
    }
    else if (index.column() == 3)
    {
        QPushButton* pushButton = new QPushButton(
                index.model()->data(index).toString(), parent);
    
        connect(pushButton, SIGNAL(clicked()), this, SLOT(wasDeleteClicked()));
    
        return pushButton;
    }
    else
    {
        return QItemDelegate::createEditor(parent, option, index);
    }
    

    }

    void MyItemDelegate::setEditorData(QWidget editor,
    const QModelIndex &index) const
    {
    if ((index.column() == 1) || (index.column() == 2))
    {
    QVariant value = index.model()->data(index);
    QComboBox
    comboBox = static_cast<QComboBox*>(editor);
    comboBox->setCurrentIndex(comboBox->findText(value.toString()));
    //comboBox->showPopup();
    }
    else if ((index.column() == 3))
    {
    //QPushButton* pushButton = static_cast<QPushButton*>(editor);
    //pushButton->click();
    }
    else
    {
    QItemDelegate::setEditorData(editor, index);
    }
    }

    void MyItemDelegate::setModelData(QWidget editor,
    QAbstractItemModel model, const QModelIndex &index) const
    {
    if ((index.column() == 1) || (index.column() == 2))
    {
    QComboBox
    comboBox = static_cast<QComboBox
    >(editor);
    QVariant value = comboBox->currentIndex();
    model->setData(index, value);
    }
    else if ((index.column() == 3))
    {

    }
    else
    {
        QItemDelegate::setModelData(editor, model, index);
    }
    

    }
    @

    In MyItemDelegate::setEditorData if I uncomment the showPopup the dropdow view is visible for a moment (a second) and then it close.

    Thanks for your answer, a greeting.



  • The following FULL example works for me (popup not disappearing).
    Please compile and check. I removed the selection model and changed MyDelegate to MyItemDelegate.

    Demo.h

    @
    #include <QMainWindow>
    #include <QItemDelegate>

    class MyItemDelegate: public QItemDelegate {
    Q_OBJECT
    public:
    MyItemDelegate(QObject *parent = 0):QItemDelegate(parent){};
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
    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;
    };

    class CTableModel: public QAbstractTableModel {
    Q_OBJECT
    public:
    CTableModel (QObject *parent=0): QAbstractTableModel(parent) {}
    int rowCount(const QModelIndex &parent) const;
    int columnCount(const QModelIndex &) const;
    QVariant data(const QModelIndex &index, int role) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role);
    };
    @

    Demo.cpp

    @
    #include <QApplication>
    #include <QPushButton>
    #include <QTreeView>
    #include <QComboBox>
    #include <QHeaderView>
    #include "Demo.h"

    int main(int argc, char **argv) {
    QApplication App(argc,argv);
    QTreeView *m_table = new QTreeView;
    m_table->setEditTriggers(QAbstractItemView::AllEditTriggers);
    m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_table->setSelectionMode(QAbstractItemView::SingleSelection);
    m_table->setDragEnabled(false);
    m_table->setAllColumnsShowFocus(true);
    m_table->setAlternatingRowColors(false);
    m_table->setRootIsDecorated(false);
    m_table->setItemsExpandable(false);
    m_table->setSortingEnabled(false);
    m_table->header()->setClickable(false);
    m_table->header()->setStretchLastSection(false);
    m_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    CTableModel *m_model = new CTableModel;
    m_table->setModel(m_model);

    MyItemDelegate* m_delegate = new MyItemDelegate;

    m_table->setItemDelegateForColumn(1, m_delegate);
    m_table->setItemDelegateForColumn(2, m_delegate);
    m_table->setItemDelegateForColumn(3, m_delegate);
    m_table->show();
    return App.exec();
    }

    void MyItemDelegate::paint(QPainter *painter,
    const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
    if ((index.column() == 1) || (index.column() == 2))
    {
    QStyleOptionComboBox comboBoxOption;
    comboBoxOption.rect = option.rect;
    comboBoxOption.state = QStyle::State_Active; // | QStyle::State_Enabled;
    comboBoxOption.currentText = index.model()->data(index).toString();
    QApplication::style()->drawComplexControl(QStyle::CC_ComboBox,
    &comboBoxOption, painter);
    QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel,
    &comboBoxOption, painter);
    }
    else
    {
    QItemDelegate::paint(painter, option, index);
    }

    }

    QWidget* MyItemDelegate::createEditor(QWidget parent,
    const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
    if ((index.column() == 1) || (index.column() == 2))
    {
    QComboBox
    comboStatus = new QComboBox(parent);
    comboStatus->addItem("i1");
    comboStatus->addItem("i2");
    comboStatus->addItem("i3");
    comboStatus->addItem("i4");
    return comboStatus;
    }
    else
    {
    return QItemDelegate::createEditor(parent, option, index);
    }
    }

    void MyItemDelegate::setEditorData(QWidget editor,
    const QModelIndex &index) const
    {
    if ((index.column() == 1) || (index.column() == 2))
    {
    QVariant value = index.model()->data(index);
    QComboBox
    comboBox = static_cast<QComboBox*>(editor);
    comboBox->setCurrentIndex(2);
    comboBox->showPopup();
    }
    else
    {
    QItemDelegate::setEditorData(editor, index);
    }
    }

    void MyItemDelegate::setModelData(QWidget editor,
    QAbstractItemModel model, const QModelIndex &index) const
    {
    if ((index.column() == 1) || (index.column() == 2))
    {
    QComboBox
    comboBox = static_cast<QComboBox
    >(editor);
    QVariant value = comboBox->currentIndex();
    model->setData(index, value);
    }
    else
    {
    QItemDelegate::setModelData(editor, model, index);
    }
    }
    int CTableModel::rowCount(const QModelIndex &) const {
    return 10;
    }
    int CTableModel::columnCount(const QModelIndex &) const {
    return 5;
    }

    QVariant CTableModel::data(const QModelIndex &index, int role) const {
    if (role == Qt::DisplayRole)
    return index.row()+index.column();
    return QVariant();
    }
    Qt::ItemFlags CTableModel::flags(const QModelIndex &) const {
    return Qt::ItemIsEnabled | Qt::ItemIsEditable;
    }
    bool CTableModel::setData(const QModelIndex &, const QVariant &, int ) {return true;}
    @



  • Hi,

    I tryed with your example on Windows platform with the last Qt version and it work perfectly, but my example on Linux platform with Qt 4.8.5 version the showPopup() not work propertly.

    I will try an other logic solution to be usable for the user with 2 click to show comboBox.

    Thanks you very much.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.