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

QTreeView - QStyledItemDelegate question



  • Hei,

    I create buttons in QTreeView cells using the code:
    Header:

    class ButtonDelegateTableView : public QStyledItemDelegate{
        Q_OBJECT
    
    public:
        explicit ButtonDelegateTableView(QObject* parent = Q_NULLPTR,
                                         Project *currentProject = new Project())
            ;QStyledItemDelegate(parent);
    
        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
    
        QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
    
        QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
    
        void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
    
        void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE;
    
        void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
    
        // vars
        Project *_currentProject;
    };
    

    .cpp:

    ButtonDelegateTableView::ButtonDelegateTableView(QObject* parent,
                                                     Project *currentProject) : QStyledItemDelegate(parent)
    {
        _currentProject = currentProject;
    }
    
    //ButtonDelegateTableView::~ButtonDelegateTableView(){};
    
    void ButtonDelegateTableView::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
    //        Q_ASSERT(index.isValid());
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);
        const QWidget *widget = option.widget;
        QStyle *style = widget ? widget->style() : QApplication::style();
        style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
    
        QStyleOptionButton editButtonOption;
        editButtonOption.text = QString("Add"); 
        editButtonOption.rect = QRect(option.rect.left()+option.rect.width()-(option.rect.height()),option.rect.top(),option.rect.height(),option.rect.height());
        editButtonOption.features = QStyleOptionButton::None;
        editButtonOption.direction = option.direction;
        editButtonOption.fontMetrics = option.fontMetrics;
        editButtonOption.palette = option.palette;
        editButtonOption.styleObject = option.styleObject;
        //
        style->drawControl(QStyle::CE_PushButton, &editButtonOption, painter, widget);
    
    }
    
    QSize ButtonDelegateTableView::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        const QSize baseSize = QStyledItemDelegate::sizeHint(option,index);
        return QSize(baseSize.width()+(2*baseSize.height()),baseSize.height());
    }
    
    QWidget* ButtonDelegateTableView::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QWidget* result = new QWidget(parent);
        result->setGeometry(option.rect);
        QWidget* baseEditor = QStyledItemDelegate::createEditor(result,option,index);
        baseEditor->setObjectName("baseEditor");
        baseEditor->setGeometry(0,0,option.rect.width()-(option.rect.height()),option.rect.height());
        QPushButton* editButton = new QPushButton("Add", result);
        editButton->setObjectName("editButton");
        editButton->setGeometry(option.rect.width()-(option.rect.height()), 0, option.rect.height(),option.rect.height());
        editButton->setToolTip("Add/edit");
    
        return result;
    }
    
    void ButtonDelegateTableView::setEditorData(QWidget *editor, const QModelIndex &index) const
    {
        QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
        Q_ASSERT(baseEditor);
        QStyledItemDelegate::setEditorData(baseEditor,index);
    }
    void ButtonDelegateTableView::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
    {
        QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
        Q_ASSERT(baseEditor);
        QStyledItemDelegate::setModelData(baseEditor,model,index);
    }
    void ButtonDelegateTableView::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        Q_UNUSED(index)
        editor->setGeometry(option.rect);
        QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
        Q_ASSERT(baseEditor);
        baseEditor->setGeometry(0,0,option.rect.width()-(option.rect.height()),option.rect.height());
        QWidget* editButton = editor->findChild<QWidget*>("editButton");
        Q_ASSERT(editButton);
        editButton->setGeometry(option.rect.width()-(option.rect.height()), 0, option.rect.height(),option.rect.height());
    
        editor->setGeometry(option.rect);
    }
    

    And the resulting table looks like this:
    4e9fa.png

    My question: How will I know the row number of the clicked "Add" button?
    The current code gives me all the time the last row number when I click on any "Add" button.

    Thanks for your responses in advance ! :)


  • Lifetime Qt Champion

    Hi,

    How do you get the information currently ?

    The index parameter does give you that from a delegate point of view.



  • @SGaist Thanks for your response.

    What I did so far is to pass the parameters to the delegate constructor and that was the reason obviously. I didn't think about the index to get the row number (I didn't know it though :)).

    Now I have another issue. How can I connect the buttons to a slot? I tried to connect within the createEditor function like following:

    QWidget* ButtonDelegateTableView::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QWidget* result = new QWidget(parent);
        result->setGeometry(option.rect);
        QWidget* baseEditor = QStyledItemDelegate::createEditor(result,option,index);
        baseEditor->setObjectName("baseEditor");
        baseEditor->setGeometry(0,0,option.rect.width()-(option.rect.height()),option.rect.height());
        QPushButton* editButton = new QPushButton("Add", result);
        editButton->setObjectName("editButton");
        editButton->setGeometry(option.rect.width()-(option.rect.height()), 0, option.rect.height(),option.rect.height());
        editButton->setToolTip("Add/edit intervals");
    
        connect(editButton, SIGNAL(clicked()), this, SLOT(pushButtonCallback(_currentProject, index.row(), _setupIndex)));
    
        return result;
    }
    

    But no chance to call the pushButtonCallback when I click on a button.



  • connect(editButton, &QPushButton::clicked, this, std::bind(&ButtonDelegateTableView::pushButtonCallback, this, _currentProject, index.row(), _setupIndex));



  • @VRonin Thanks VRonin. But I got following 2 errors with your connect script:

    • C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\type_traits:1468: error: C2672: 'std::invoke': no matching overloaded function found

    • C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\type_traits:1468: error: C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'

    Is it related to the slot function definition? It is as following:

    void ButtonDelegateTableView::pushButtonCallback(Project *currentProject, int rowNumber, int setupIndex)
    


  • you probably just forgot to #include <functional>



  • @VRonin Yes, I forgot to add that (I didn't know it to be honest :))

    It is added but I still get the same errors.



  • is ButtonDelegateTableView::pushButtonCallback overloaded?



  • @VRonin Nope. I also tested it without any arguments as following and still have the same error:

    connect(editButton, &QPushButton::clicked, this, std::bind(&ButtonDelegateTableView::pushButtonCallback, this));
    
    void ButtonDelegateTableView::pushButtonCallback()
    


  • @VRonin I made it run using following lambda expression:

        connect(editButton, &QPushButton::clicked, [=]()
        {
           pushButtonCallback( _currentProject, index.row(), _setupIndex);
        } );
    

    Thanks for your response anyway.


Log in to reply