Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Add widget right aligned to a QTableWidget cell
Forum Updated to NodeBB v4.3 + New Features

Add widget right aligned to a QTableWidget cell

Scheduled Pinned Locked Moved Solved General and Desktop
46 Posts 4 Posters 8.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • VRoninV VRonin

    May setIndexWidget burn in hell forever and beyond!
    https://forum.qt.io/post/475871

    H Offline
    H Offline
    hbatalha
    wrote on last edited by
    #8

    @VRonin I tried it but I am facing some problems, the buttons are only visible when the row is selected and I can't click it.
    Also, how do I get the button and connect it outside the delegate class?

    VRoninV 1 Reply Last reply
    0
    • H hbatalha

      @VRonin I tried it but I am facing some problems, the buttons are only visible when the row is selected and I can't click it.
      Also, how do I get the button and connect it outside the delegate class?

      VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #9

      @hbatalha said in Add widget right aligned to a QTableWidget cell:

      the buttons are only visible when the row is selected

      Just remove:

      if(!(option.state & QStyle::State_Selected))
                  return;
      

      and I can't click it.

      You need to adjust the edit trigger of the view: https://doc.qt.io/qt-5/qabstractitemview.html#editTriggers-prop

      how do I get the button and connect it outside the delegate class?

      create a signal in the delegate, something like Q_SIGNAL void clicked(const QModelIndex &index); and replace connect(editButton,&QPushButton::clicked,[](){qDebug("Edit");}); with connect(editButton,&QPushButton::clicked,this,std::bind(&TailButtonsDelegate::clicked,this,index));

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      H 1 Reply Last reply
      2
      • VRoninV VRonin

        @hbatalha said in Add widget right aligned to a QTableWidget cell:

        the buttons are only visible when the row is selected

        Just remove:

        if(!(option.state & QStyle::State_Selected))
                    return;
        

        and I can't click it.

        You need to adjust the edit trigger of the view: https://doc.qt.io/qt-5/qabstractitemview.html#editTriggers-prop

        how do I get the button and connect it outside the delegate class?

        create a signal in the delegate, something like Q_SIGNAL void clicked(const QModelIndex &index); and replace connect(editButton,&QPushButton::clicked,[](){qDebug("Edit");}); with connect(editButton,&QPushButton::clicked,this,std::bind(&TailButtonsDelegate::clicked,this,index));

        H Offline
        H Offline
        hbatalha
        wrote on last edited by
        #10

        @VRonin I getting this error when trying to create a signal in the delegate:

        C:\msys64\mingw64\include\c++\10.3.0\functional:460: error: no type named 'type' in 'class std::result_of<void (TailButtonsDelegate::*&(const TailButtonsDelegate*&, QModelIndex&))(const QModelIndex&)>'
        C:/msys64/mingw64/include/c++/10.3.0/functional:494:9:   required from 'struct QtPrivate::FunctorReturnType<std::_Bind<void (TailButtonsDelegate::*(const TailButtonsDelegate*, QModelIndex))(const QModelIndex&)>, QtPrivate::List<> >'
        C:/Qt/6.2.0/mingw81_64/include/QtCore/qobject.h:306:158:   required from 'static typename std::enable_if<(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 (QAbstractButton::*)(bool); Func2 = std::_Bind<void (TailButtonsDelegate::*(const TailButtonsDelegate*, QModelIndex))(const QModelIndex&)>; typename std::enable_if<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1), QMetaObject::Connection>::type = QMetaObject::Connection; typename QtPrivate::FunctionPointer<Func>::Object = QAbstractButton]'
        release\../delegate.h:55:108:   required from here
        C:/msys64/mingw64/include/c++/10.3.0/functional:460:8: error: no type named 'type' in 'class std::result_of<void (TailButtonsDelegate::*&(const TailButtonsDelegate*&, QModelIndex&))(const QModelIndex&)>'
          460 |  using _Res_type_impl
              |        ^~~~~~~~~~~~~~
        

        Also, I have a question: what's so wrong with setIndexWidget, creating a delegate seems so complex so I am asking what are the advantages of it over setIndexWidget?

        VRoninV 1 Reply Last reply
        0
        • H hbatalha

          @VRonin I getting this error when trying to create a signal in the delegate:

          C:\msys64\mingw64\include\c++\10.3.0\functional:460: error: no type named 'type' in 'class std::result_of<void (TailButtonsDelegate::*&(const TailButtonsDelegate*&, QModelIndex&))(const QModelIndex&)>'
          C:/msys64/mingw64/include/c++/10.3.0/functional:494:9:   required from 'struct QtPrivate::FunctorReturnType<std::_Bind<void (TailButtonsDelegate::*(const TailButtonsDelegate*, QModelIndex))(const QModelIndex&)>, QtPrivate::List<> >'
          C:/Qt/6.2.0/mingw81_64/include/QtCore/qobject.h:306:158:   required from 'static typename std::enable_if<(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 (QAbstractButton::*)(bool); Func2 = std::_Bind<void (TailButtonsDelegate::*(const TailButtonsDelegate*, QModelIndex))(const QModelIndex&)>; typename std::enable_if<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1), QMetaObject::Connection>::type = QMetaObject::Connection; typename QtPrivate::FunctionPointer<Func>::Object = QAbstractButton]'
          release\../delegate.h:55:108:   required from here
          C:/msys64/mingw64/include/c++/10.3.0/functional:460:8: error: no type named 'type' in 'class std::result_of<void (TailButtonsDelegate::*&(const TailButtonsDelegate*&, QModelIndex&))(const QModelIndex&)>'
            460 |  using _Res_type_impl
                |        ^~~~~~~~~~~~~~
          

          Also, I have a question: what's so wrong with setIndexWidget, creating a delegate seems so complex so I am asking what are the advantages of it over setIndexWidget?

          VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #11

          @hbatalha said in Add widget right aligned to a QTableWidget cell:

          I getting this error when trying to create a signal in the delegate:

          Can you show your code?

          what's so wrong with setIndexWidget, creating a delegate seems so complex so I am asking what are the advantages of it over setIndexWidget?

          Try creating 1000 rows and scroll through them. You'll realise very quick what the problem is. setIndexWidget is a HOG on resources

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          H 1 Reply Last reply
          3
          • VRoninV VRonin

            @hbatalha said in Add widget right aligned to a QTableWidget cell:

            I getting this error when trying to create a signal in the delegate:

            Can you show your code?

            what's so wrong with setIndexWidget, creating a delegate seems so complex so I am asking what are the advantages of it over setIndexWidget?

            Try creating 1000 rows and scroll through them. You'll realise very quick what the problem is. setIndexWidget is a HOG on resources

            H Offline
            H Offline
            hbatalha
            wrote on last edited by
            #12

            @VRonin Sorry for the really late reply, I have been working offline due to internet cut.

            @VRonin said in Add widget right aligned to a QTableWidget cell:

            Try creating 1000 rows and scroll through them. You'll realise very quick what the problem is. setIndexWidget is a HOG on resources

            I Will try that, I am curious to see it

            Can you show your code?

            #ifndef TAILBUTTONSDELEGATE_H
            #define TAILBUTTONSDELEGATE_H
            
            #include <QApplication>
            #include <QTableView>
            #include <QStandardItemModel>
            #include <QStyledItemDelegate>
            #include <QHeaderView>
            #include <QPushButton>
            
            class TailButtonsDelegate : public QStyledItemDelegate
            {
                Q_OBJECT
                Q_DISABLE_COPY(TailButtonsDelegate)
            
            public:
                explicit TailButtonsDelegate(QObject* parent = Q_NULLPTR)
                    :QStyledItemDelegate(parent)
                {}
                void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                {
                    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(); //use emoji for text, optionally you can use icon + iconSize
                    editButtonOption.rect = QRect(option.rect.left()+option.rect.width()-(2*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;
                    QStyleOptionButton removeButtonOption(editButtonOption);
                    removeButtonOption.text = QString(); //use emoji for text, optionally you can use icon + iconSize
                    removeButtonOption.rect = QRect(option.rect.left()+option.rect.width()-option.rect.height(),option.rect.top(),option.rect.height(),option.rect.height());
                    style->drawControl(QStyle::CE_PushButton, &editButtonOption, painter, widget);
                    style->drawControl(QStyle::CE_PushButton, &removeButtonOption, painter, widget);
                }
                QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                {
                    const QSize baseSize = QStyledItemDelegate::sizeHint(option,index);
                    return QSize(baseSize.width()+(2*baseSize.height()),baseSize.height());
                }
                QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                {
                    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()-(2*option.rect.height()),option.rect.height());
                    QPushButton* editButton = new QPushButton(result);
                    editButton->setObjectName("editButton");
                    editButton->setGeometry(option.rect.width()-(2*option.rect.height()), 0, option.rect.height(),option.rect.height());
                    connect(editButton,&QPushButton::clicked,[]()
                    {
                        qDebug("Edit");
                    });
                    QPushButton* removeButton = new QPushButton(result);
                    removeButton->setObjectName("removeButton");
                    removeButton->setGeometry(option.rect.width()-option.rect.height(), 0, option.rect.height(),option.rect.height());
                    connect(editButton,&QPushButton::clicked,this,std::bind(&TailButtonsDelegate::clicked,this,index));
                    return result;
                }
                void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE
                {
                    QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                    Q_ASSERT(baseEditor);
                    QStyledItemDelegate::setEditorData(baseEditor,index);
                }
                void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE
                {
                    QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                    Q_ASSERT(baseEditor);
                    QStyledItemDelegate::setModelData(baseEditor,model,index);
                }
                void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                {
                    Q_UNUSED(index)
                    editor->setGeometry(option.rect);
                    QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                    Q_ASSERT(baseEditor);
                    baseEditor->setGeometry(0,0,option.rect.width()-(2*option.rect.height()),option.rect.height());
                    QWidget* editButton = editor->findChild<QWidget*>("editButton");
                    Q_ASSERT(editButton);
                    editButton->setGeometry(option.rect.width()-(2*option.rect.height()), 0, option.rect.height(),option.rect.height());
                    QWidget* removeButton = editor->findChild<QWidget*>("removeButton");
                    Q_ASSERT(removeButton);
                    removeButton->setGeometry(option.rect.width()-option.rect.height(), 0, option.rect.height(),option.rect.height());
                    editor->setGeometry(option.rect);
                }
            
                Q_SIGNAL void clicked(const QModelIndex &index);
            };
            
            #endif // TAILBUTTONSDELEGATE_H
            

            Also I want to set the button size to setFixedSize(10, 10); but I have been having problems controlling the size. For the time being I have being using this version using setIndexWidget

                QWidget* widget = new QWidget;
            
                QPushButton* detailsButton = new QPushButton;
                detailsButton->setFixedSize(10, 10);
            
                QHBoxLayout* hLayout = new QHBoxLayout;
                hLayout->addStretch();
                hLayout->addWidget(detailsButton);
                widget->setLayout(hLayout);
            
                ui->tableWidget->setIndexWidget(ui->tableWidget->model()->index(row, 0), widget);
            

            So above is what I am trying to achieve using delegate.

            VRoninV 1 Reply Last reply
            0
            • H Offline
              H Offline
              hbatalha
              wrote on last edited by
              #13

              Also the button is still not clickable

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #14

                Sorry for the delay in getting back to you, I've been offline for a few days. Try this:

                #ifndef TAILBUTTONDELEGATE_H
                #define TAILBUTTONDELEGATE_H
                
                #include <QApplication>
                #include <QStyledItemDelegate>
                #include <QPushButton>
                #include <QMouseEvent>
                class TailButtonDelegate : public QStyledItemDelegate
                {
                    Q_OBJECT
                #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                    Q_DISABLE_COPY_MOVE(TailButtonDelegate)
                #else
                    Q_DISABLE_COPY(TailButtonDelegate)
                #endif
                public:
                    explicit TailButtonDelegate(QObject* parent = Q_NULLPTR)
                        :QStyledItemDelegate(parent)
                    {}
                    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                    {
                        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 buttonOption = buttonOptions(opt);
                        style->drawControl(QStyle::CE_PushButton, &buttonOption, painter, widget);
                    }
                    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                    {
                        QStyleOptionViewItem opt = option;
                        initStyleOption(&opt, index);
                        const QSize baseSize = QStyledItemDelegate::sizeHint(option,index);
                        const QRect butRect = buttonRect(opt);
                        return QSize(baseSize.width()+butRect.width(),qMax(butRect.height(),baseSize.height()));
                    }
                    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                    {
                        QWidget* result = new QWidget(parent);
                        result->setGeometry(option.rect);
                        QWidget* baseEditor = QStyledItemDelegate::createEditor(result,option,index);
                        result->setFocusProxy(baseEditor);
                        QStyleOptionViewItem opt = option;
                        initStyleOption(&opt, index);
                        const QRect butRect = buttonRect(opt);
                        baseEditor->setObjectName("baseEditor");
                        baseEditor->setGeometry(0,0,opt.rect.width()-butRect.width(),opt.rect.height());
                        QPushButton* extraButton = new QPushButton(result);
                        extraButton->setObjectName("extraButton");
                        extraButton->setText(m_buttonText);
                        extraButton->setIcon(m_buttonIcon);
                        extraButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
                        connect(extraButton,&QPushButton::clicked,this,&TailButtonDelegate::clickedHelper);
                        return result;
                    }
                    void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE
                    {
                        currentIndex = index;
                        QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                        Q_ASSERT(baseEditor);
                        QStyledItemDelegate::setEditorData(baseEditor,index);
                    }
                    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE
                    {
                        QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                        Q_ASSERT(baseEditor);
                        QStyledItemDelegate::setModelData(baseEditor,model,index);
                    }
                    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                    {
                        QStyleOptionViewItem opt = option;
                        initStyleOption(&opt, index);
                        editor->setGeometry(opt.rect);
                        const QRect butRect = buttonRect(opt);
                        QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                        Q_ASSERT(baseEditor);
                        baseEditor->setGeometry(0,0,opt.rect.width()-butRect.width(),opt.rect.height());
                        QWidget* extraButton = editor->findChild<QWidget*>("extraButton");
                        Q_ASSERT(extraButton);
                        extraButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
                    }
                    const QString buttonText() const
                    {
                        return m_buttonText;
                    }
                    void setButtonText(const QString &newButtonText)
                    {
                        m_buttonText = newButtonText;
                    }
                    const QIcon &buttonIcon() const
                    {
                        return m_buttonIcon;
                    }
                    void setButtonIcon(const QIcon &newButtonIcon)
                    {
                        m_buttonIcon = newButtonIcon;
                    }
                Q_SIGNALS:
                    void buttonClicked(const QModelIndex &index);
                protected:
                    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) Q_DECL_OVERRIDE{
                        Q_ASSERT(event);
                        Q_ASSERT(model);
                        Qt::ItemFlags flags = model->flags(index);
                        if ((option.state & QStyle::State_Enabled) && (flags & Qt::ItemIsEnabled)){
                            if (event->type() == QEvent::MouseButtonRelease) {
                                QStyleOptionViewItem viewOpt(option);
                                initStyleOption(&viewOpt, index);
                                const QRect butRect = buttonRect(viewOpt);
                                QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                if (me->button() == Qt::LeftButton && butRect.contains(me->pos())){
                                    currentIndex = index;
                                    clickedHelper();
                                }
                            }
                        }
                        return QStyledItemDelegate::editorEvent(event,model,option,index);
                    }
                    virtual QStyleOptionButton buttonOptions(const QStyleOptionViewItem &option, bool skipRct=false) const{
                        const QWidget *widget = option.widget;
                        QStyle *style = widget ? widget->style() : QApplication::style();
                        int buttonIconSize = style->pixelMetric(QStyle::PM_ButtonIconSize, 0, widget);
                        QStyleOptionButton buttonOption;
                        buttonOption.text = m_buttonText;
                        buttonOption.icon = m_buttonIcon;
                        buttonOption.iconSize = (QSize(buttonIconSize,buttonIconSize));
                        buttonOption.rect = skipRct ? QRect() : buttonRect(option);
                        buttonOption.features = QStyleOptionButton::None;
                        buttonOption.direction = option.direction;
                        buttonOption.fontMetrics = option.fontMetrics;
                        buttonOption.palette = option.palette;
                        buttonOption.styleObject = option.styleObject;
                        buttonOption.state = option.state;
                        return buttonOption;
                    }
                    virtual QRect buttonRect(const QStyleOptionViewItem &option) const{
                        const QStyleOptionButton buttonOption = buttonOptions(option,true);
                        const QWidget *widget = option.widget;
                        QStyle *style = widget ? widget->style() : QApplication::style();
                        QSize buttonSize = style->sizeFromContents(QStyle::CT_PushButton, &buttonOption, QSize(), widget);
                        buttonSize.setWidth(qMin(buttonSize.width(),option.rect.width()/2));
                        return QRect(option.rect.left()+option.rect.width()-buttonSize.width(),option.rect.top(),buttonSize.width(),qMax(buttonSize.height(),option.rect.height()));
                    }
                private:
                    mutable QModelIndex currentIndex;
                    QString m_buttonText;
                    QIcon m_buttonIcon;
                    void clickedHelper(){buttonClicked(currentIndex);}
                };
                
                #endif // TAILBUTTONDELEGATE_H
                

                Then you can use it with something like:

                int main(int argc, char *argv[])
                {
                    QApplication app(argc,argv);
                    QTableWidget wid(2,2);
                    TailButtonDelegate *butDelegate = new TailButtonDelegate(&wid);
                    butDelegate->setButtonText("Test");
                    QPixmap bluePixmap(20,20);
                    bluePixmap.fill(Qt::blue);
                    QIcon blueIcon;
                    blueIcon.addPixmap(bluePixmap);
                    butDelegate->setButtonIcon(blueIcon);
                    QObject::connect(butDelegate,&TailButtonDelegate::buttonClicked,[](const QModelIndex& index){qDebug() << "Clicked " << index;});
                    wid.setItemDelegate(butDelegate);
                    wid.show();
                    return app.exec();
                
                }
                

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                H 1 Reply Last reply
                2
                • H hbatalha

                  @VRonin Sorry for the really late reply, I have been working offline due to internet cut.

                  @VRonin said in Add widget right aligned to a QTableWidget cell:

                  Try creating 1000 rows and scroll through them. You'll realise very quick what the problem is. setIndexWidget is a HOG on resources

                  I Will try that, I am curious to see it

                  Can you show your code?

                  #ifndef TAILBUTTONSDELEGATE_H
                  #define TAILBUTTONSDELEGATE_H
                  
                  #include <QApplication>
                  #include <QTableView>
                  #include <QStandardItemModel>
                  #include <QStyledItemDelegate>
                  #include <QHeaderView>
                  #include <QPushButton>
                  
                  class TailButtonsDelegate : public QStyledItemDelegate
                  {
                      Q_OBJECT
                      Q_DISABLE_COPY(TailButtonsDelegate)
                  
                  public:
                      explicit TailButtonsDelegate(QObject* parent = Q_NULLPTR)
                          :QStyledItemDelegate(parent)
                      {}
                      void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                      {
                          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(); //use emoji for text, optionally you can use icon + iconSize
                          editButtonOption.rect = QRect(option.rect.left()+option.rect.width()-(2*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;
                          QStyleOptionButton removeButtonOption(editButtonOption);
                          removeButtonOption.text = QString(); //use emoji for text, optionally you can use icon + iconSize
                          removeButtonOption.rect = QRect(option.rect.left()+option.rect.width()-option.rect.height(),option.rect.top(),option.rect.height(),option.rect.height());
                          style->drawControl(QStyle::CE_PushButton, &editButtonOption, painter, widget);
                          style->drawControl(QStyle::CE_PushButton, &removeButtonOption, painter, widget);
                      }
                      QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                      {
                          const QSize baseSize = QStyledItemDelegate::sizeHint(option,index);
                          return QSize(baseSize.width()+(2*baseSize.height()),baseSize.height());
                      }
                      QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                      {
                          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()-(2*option.rect.height()),option.rect.height());
                          QPushButton* editButton = new QPushButton(result);
                          editButton->setObjectName("editButton");
                          editButton->setGeometry(option.rect.width()-(2*option.rect.height()), 0, option.rect.height(),option.rect.height());
                          connect(editButton,&QPushButton::clicked,[]()
                          {
                              qDebug("Edit");
                          });
                          QPushButton* removeButton = new QPushButton(result);
                          removeButton->setObjectName("removeButton");
                          removeButton->setGeometry(option.rect.width()-option.rect.height(), 0, option.rect.height(),option.rect.height());
                          connect(editButton,&QPushButton::clicked,this,std::bind(&TailButtonsDelegate::clicked,this,index));
                          return result;
                      }
                      void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE
                      {
                          QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                          Q_ASSERT(baseEditor);
                          QStyledItemDelegate::setEditorData(baseEditor,index);
                      }
                      void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE
                      {
                          QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                          Q_ASSERT(baseEditor);
                          QStyledItemDelegate::setModelData(baseEditor,model,index);
                      }
                      void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                      {
                          Q_UNUSED(index)
                          editor->setGeometry(option.rect);
                          QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                          Q_ASSERT(baseEditor);
                          baseEditor->setGeometry(0,0,option.rect.width()-(2*option.rect.height()),option.rect.height());
                          QWidget* editButton = editor->findChild<QWidget*>("editButton");
                          Q_ASSERT(editButton);
                          editButton->setGeometry(option.rect.width()-(2*option.rect.height()), 0, option.rect.height(),option.rect.height());
                          QWidget* removeButton = editor->findChild<QWidget*>("removeButton");
                          Q_ASSERT(removeButton);
                          removeButton->setGeometry(option.rect.width()-option.rect.height(), 0, option.rect.height(),option.rect.height());
                          editor->setGeometry(option.rect);
                      }
                  
                      Q_SIGNAL void clicked(const QModelIndex &index);
                  };
                  
                  #endif // TAILBUTTONSDELEGATE_H
                  

                  Also I want to set the button size to setFixedSize(10, 10); but I have been having problems controlling the size. For the time being I have being using this version using setIndexWidget

                      QWidget* widget = new QWidget;
                  
                      QPushButton* detailsButton = new QPushButton;
                      detailsButton->setFixedSize(10, 10);
                  
                      QHBoxLayout* hLayout = new QHBoxLayout;
                      hLayout->addStretch();
                      hLayout->addWidget(detailsButton);
                      widget->setLayout(hLayout);
                  
                      ui->tableWidget->setIndexWidget(ui->tableWidget->model()->index(row, 0), widget);
                  

                  So above is what I am trying to achieve using delegate.

                  VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by
                  #15

                  @hbatalha said in Add widget right aligned to a QTableWidget cell:

                  Also I want to set the button size to setFixedSize(10, 10);

                  To do this in the example above you'd need to tweak the buttonRect() method to something like

                  virtual QRect buttonRect(const QStyleOptionViewItem &option) const{
                      return QRect(option.rect.left()+option.rect.width()-10,option.rect.top(),10,10);
                  }
                  

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  1 Reply Last reply
                  0
                  • VRoninV VRonin

                    Sorry for the delay in getting back to you, I've been offline for a few days. Try this:

                    #ifndef TAILBUTTONDELEGATE_H
                    #define TAILBUTTONDELEGATE_H
                    
                    #include <QApplication>
                    #include <QStyledItemDelegate>
                    #include <QPushButton>
                    #include <QMouseEvent>
                    class TailButtonDelegate : public QStyledItemDelegate
                    {
                        Q_OBJECT
                    #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                        Q_DISABLE_COPY_MOVE(TailButtonDelegate)
                    #else
                        Q_DISABLE_COPY(TailButtonDelegate)
                    #endif
                    public:
                        explicit TailButtonDelegate(QObject* parent = Q_NULLPTR)
                            :QStyledItemDelegate(parent)
                        {}
                        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            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 buttonOption = buttonOptions(opt);
                            style->drawControl(QStyle::CE_PushButton, &buttonOption, painter, widget);
                        }
                        QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            QStyleOptionViewItem opt = option;
                            initStyleOption(&opt, index);
                            const QSize baseSize = QStyledItemDelegate::sizeHint(option,index);
                            const QRect butRect = buttonRect(opt);
                            return QSize(baseSize.width()+butRect.width(),qMax(butRect.height(),baseSize.height()));
                        }
                        QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            QWidget* result = new QWidget(parent);
                            result->setGeometry(option.rect);
                            QWidget* baseEditor = QStyledItemDelegate::createEditor(result,option,index);
                            result->setFocusProxy(baseEditor);
                            QStyleOptionViewItem opt = option;
                            initStyleOption(&opt, index);
                            const QRect butRect = buttonRect(opt);
                            baseEditor->setObjectName("baseEditor");
                            baseEditor->setGeometry(0,0,opt.rect.width()-butRect.width(),opt.rect.height());
                            QPushButton* extraButton = new QPushButton(result);
                            extraButton->setObjectName("extraButton");
                            extraButton->setText(m_buttonText);
                            extraButton->setIcon(m_buttonIcon);
                            extraButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
                            connect(extraButton,&QPushButton::clicked,this,&TailButtonDelegate::clickedHelper);
                            return result;
                        }
                        void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            currentIndex = index;
                            QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                            Q_ASSERT(baseEditor);
                            QStyledItemDelegate::setEditorData(baseEditor,index);
                        }
                        void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                            Q_ASSERT(baseEditor);
                            QStyledItemDelegate::setModelData(baseEditor,model,index);
                        }
                        void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            QStyleOptionViewItem opt = option;
                            initStyleOption(&opt, index);
                            editor->setGeometry(opt.rect);
                            const QRect butRect = buttonRect(opt);
                            QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                            Q_ASSERT(baseEditor);
                            baseEditor->setGeometry(0,0,opt.rect.width()-butRect.width(),opt.rect.height());
                            QWidget* extraButton = editor->findChild<QWidget*>("extraButton");
                            Q_ASSERT(extraButton);
                            extraButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
                        }
                        const QString buttonText() const
                        {
                            return m_buttonText;
                        }
                        void setButtonText(const QString &newButtonText)
                        {
                            m_buttonText = newButtonText;
                        }
                        const QIcon &buttonIcon() const
                        {
                            return m_buttonIcon;
                        }
                        void setButtonIcon(const QIcon &newButtonIcon)
                        {
                            m_buttonIcon = newButtonIcon;
                        }
                    Q_SIGNALS:
                        void buttonClicked(const QModelIndex &index);
                    protected:
                        bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) Q_DECL_OVERRIDE{
                            Q_ASSERT(event);
                            Q_ASSERT(model);
                            Qt::ItemFlags flags = model->flags(index);
                            if ((option.state & QStyle::State_Enabled) && (flags & Qt::ItemIsEnabled)){
                                if (event->type() == QEvent::MouseButtonRelease) {
                                    QStyleOptionViewItem viewOpt(option);
                                    initStyleOption(&viewOpt, index);
                                    const QRect butRect = buttonRect(viewOpt);
                                    QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                    if (me->button() == Qt::LeftButton && butRect.contains(me->pos())){
                                        currentIndex = index;
                                        clickedHelper();
                                    }
                                }
                            }
                            return QStyledItemDelegate::editorEvent(event,model,option,index);
                        }
                        virtual QStyleOptionButton buttonOptions(const QStyleOptionViewItem &option, bool skipRct=false) const{
                            const QWidget *widget = option.widget;
                            QStyle *style = widget ? widget->style() : QApplication::style();
                            int buttonIconSize = style->pixelMetric(QStyle::PM_ButtonIconSize, 0, widget);
                            QStyleOptionButton buttonOption;
                            buttonOption.text = m_buttonText;
                            buttonOption.icon = m_buttonIcon;
                            buttonOption.iconSize = (QSize(buttonIconSize,buttonIconSize));
                            buttonOption.rect = skipRct ? QRect() : buttonRect(option);
                            buttonOption.features = QStyleOptionButton::None;
                            buttonOption.direction = option.direction;
                            buttonOption.fontMetrics = option.fontMetrics;
                            buttonOption.palette = option.palette;
                            buttonOption.styleObject = option.styleObject;
                            buttonOption.state = option.state;
                            return buttonOption;
                        }
                        virtual QRect buttonRect(const QStyleOptionViewItem &option) const{
                            const QStyleOptionButton buttonOption = buttonOptions(option,true);
                            const QWidget *widget = option.widget;
                            QStyle *style = widget ? widget->style() : QApplication::style();
                            QSize buttonSize = style->sizeFromContents(QStyle::CT_PushButton, &buttonOption, QSize(), widget);
                            buttonSize.setWidth(qMin(buttonSize.width(),option.rect.width()/2));
                            return QRect(option.rect.left()+option.rect.width()-buttonSize.width(),option.rect.top(),buttonSize.width(),qMax(buttonSize.height(),option.rect.height()));
                        }
                    private:
                        mutable QModelIndex currentIndex;
                        QString m_buttonText;
                        QIcon m_buttonIcon;
                        void clickedHelper(){buttonClicked(currentIndex);}
                    };
                    
                    #endif // TAILBUTTONDELEGATE_H
                    

                    Then you can use it with something like:

                    int main(int argc, char *argv[])
                    {
                        QApplication app(argc,argv);
                        QTableWidget wid(2,2);
                        TailButtonDelegate *butDelegate = new TailButtonDelegate(&wid);
                        butDelegate->setButtonText("Test");
                        QPixmap bluePixmap(20,20);
                        bluePixmap.fill(Qt::blue);
                        QIcon blueIcon;
                        blueIcon.addPixmap(bluePixmap);
                        butDelegate->setButtonIcon(blueIcon);
                        QObject::connect(butDelegate,&TailButtonDelegate::buttonClicked,[](const QModelIndex& index){qDebug() << "Clicked " << index;});
                        wid.setItemDelegate(butDelegate);
                        wid.show();
                        return app.exec();
                    
                    }
                    
                    H Offline
                    H Offline
                    hbatalha
                    wrote on last edited by hbatalha
                    #16

                    @VRonin It's working greatly, thanks, but I want to access some QPushButton methods, namely setCheckable, isChecked, setChecked, setToolTip. Also I want to emit signal when the mouse enters the button, I tried doind that but it's not working.
                    This is what I have tried to get a signal when mouse enters the button

                    #ifndef TAILBUTTONSDELEGATE_H
                    #define TAILBUTTONSDELEGATE_H
                    
                    #include <QApplication>
                    #include <QStyledItemDelegate>
                    #include <QPushButton>
                    #include <QMouseEvent>
                    
                    class MyButton : public QPushButton
                    {
                        Q_OBJECT
                    
                    public:
                        MyButton(QWidget* parent = 0) : QPushButton(parent) {}
                        ~MyButton() {};
                    
                    signals:
                        void mouseIn();
                    
                    protected:
                        void enterEvent(QEnterEvent*) override
                        {
                            emit mouseIn();
                        }
                    };
                    
                    class TailButtonDelegate : public QStyledItemDelegate
                    {
                        Q_OBJECT
                    #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                        Q_DISABLE_COPY_MOVE(TailButtonDelegate)
                    #else
                        Q_DISABLE_COPY(TailButtonDelegate)
                    #endif
                    public:
                        explicit TailButtonDelegate(QObject* parent = Q_NULLPTR)
                            :QStyledItemDelegate(parent)
                        {}
                        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            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 buttonOption = buttonOptions(opt);
                            style->drawControl(QStyle::CE_PushButton, &buttonOption, painter, widget);
                        }
                        QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            QStyleOptionViewItem opt = option;
                            initStyleOption(&opt, index);
                            const QSize baseSize = QStyledItemDelegate::sizeHint(option,index);
                            const QRect butRect = buttonRect(opt);
                            return QSize(baseSize.width()+butRect.width(),qMax(butRect.height(),baseSize.height()));
                        }
                        QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            QWidget* result = new QWidget(parent);
                            result->setGeometry(option.rect);
                            QWidget* baseEditor = QStyledItemDelegate::createEditor(result,option,index);
                            result->setFocusProxy(baseEditor);
                            QStyleOptionViewItem opt = option;
                            initStyleOption(&opt, index);
                            const QRect butRect = buttonRect(opt);
                            baseEditor->setObjectName("baseEditor");
                            baseEditor->setGeometry(0,0,opt.rect.width()-butRect.width(),opt.rect.height());
                            MyButton* myButton = new MyButton(result);
                            myButton->setObjectName("myButton");
                            myButton->setText(m_buttonText);
                            myButton->setIcon(m_buttonIcon);
                            myButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
                            connect(myButton, &MyButton::clicked, this, &TailButtonDelegate::clickedHelper);
                            connect(myButton, &MyButton::mouseIn, this, &TailButtonDelegate::mouseInHelper);
                            return result;
                        }
                        void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            currentIndex = index;
                            QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                            Q_ASSERT(baseEditor);
                            QStyledItemDelegate::setEditorData(baseEditor,index);
                        }
                        void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                            Q_ASSERT(baseEditor);
                            QStyledItemDelegate::setModelData(baseEditor,model,index);
                        }
                        void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                        {
                            QStyleOptionViewItem opt = option;
                            initStyleOption(&opt, index);
                            editor->setGeometry(opt.rect);
                            const QRect butRect = buttonRect(opt);
                            QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
                            Q_ASSERT(baseEditor);
                            baseEditor->setGeometry(0,0,opt.rect.width()-butRect.width(),opt.rect.height());
                            QWidget* myButton = editor->findChild<QWidget*>("myButton");
                            Q_ASSERT(myButton);
                            myButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
                        }
                        const QString buttonText() const
                        {
                            return m_buttonText;
                        }
                        void setButtonText(const QString &newButtonText)
                        {
                            m_buttonText = newButtonText;
                        }
                        const QIcon &buttonIcon() const
                        {
                            return m_buttonIcon;
                        }
                        void setButtonIcon(const QIcon &newButtonIcon)
                        {
                            m_buttonIcon = newButtonIcon;
                        }
                    Q_SIGNALS:
                        void clicked(const QModelIndex &index);
                        void mouseIn(const QModelIndex &index);
                    protected:
                        bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) Q_DECL_OVERRIDE
                        {
                            Q_ASSERT(event);
                            Q_ASSERT(model);
                            Qt::ItemFlags flags = model->flags(index);
                            if ((option.state & QStyle::State_Enabled) && (flags & Qt::ItemIsEnabled))
                            {
                                if (event->type() == QEvent::MouseButtonRelease)
                                {
                                    QStyleOptionViewItem viewOpt(option);
                                    initStyleOption(&viewOpt, index);
                                    const QRect butRect = buttonRect(viewOpt);
                                    QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                    if (me->button() == Qt::LeftButton && butRect.contains(me->pos()))
                                    {
                                        currentIndex = index;
                                        clickedHelper();
                                    }
                                }
                                if (event->type() == QEvent::Enter)
                                {
                                    {
                                        currentIndex = index;
                                        mouseInHelper();
                                    }
                                }
                            }
                            return QStyledItemDelegate::editorEvent(event,model,option,index);
                        }
                        virtual QStyleOptionButton buttonOptions(const QStyleOptionViewItem &option, bool skipRct=false) const
                        {
                            const QWidget *widget = option.widget;
                            QStyle *style = widget ? widget->style() : QApplication::style();
                            int buttonIconSize = style->pixelMetric(QStyle::PM_ButtonIconSize, 0, widget);
                            QStyleOptionButton buttonOption;
                            buttonOption.text = m_buttonText;
                            buttonOption.icon = m_buttonIcon;
                            buttonOption.iconSize = (QSize(buttonIconSize,buttonIconSize));
                            buttonOption.rect = skipRct ? QRect() : buttonRect(option);
                            buttonOption.features = QStyleOptionButton::None;
                            buttonOption.direction = option.direction;
                            buttonOption.fontMetrics = option.fontMetrics;
                            buttonOption.palette = option.palette;
                            buttonOption.styleObject = option.styleObject;
                            buttonOption.state = option.state;
                            return buttonOption;
                        }
                        virtual QRect buttonRect(const QStyleOptionViewItem &option) const
                        {
                            const QStyleOptionButton buttonOption = buttonOptions(option,true);
                            const QWidget *widget = option.widget;
                            QStyle *style = widget ? widget->style() : QApplication::style();
                            QSize buttonSize = style->sizeFromContents(QStyle::CT_PushButton, &buttonOption, QSize(), widget);
                            buttonSize.setWidth(qMin(buttonSize.width(),option.rect.width()/2));
                            return QRect(option.rect.left()+option.rect.width()-10,option.rect.top(),10,10);
                        }
                    private:
                        mutable QModelIndex currentIndex;
                        QString m_buttonText;
                        QIcon m_buttonIcon;
                        void clickedHelper()
                        {
                            clicked(currentIndex);
                        }
                        void mouseInHelper()
                        {
                            mouseIn(currentIndex);
                        }
                    };
                    
                    #endif // TAILBUTTONSDELEGATE_H
                    

                    but it is not working.

                    1 Reply Last reply
                    0
                    • H Offline
                      H Offline
                      hbatalha
                      wrote on last edited by hbatalha
                      #17

                      Also I would like have the button in the middle of the cell(top - bottom), this when set the size to (10,10)

                      VRoninV 1 Reply Last reply
                      0
                      • H Offline
                        H Offline
                        hbatalha
                        wrote on last edited by hbatalha
                        #18

                        Update: I was able to solve all the problems mentioned above except for the mouse over event signal.
                        So now I just want a way to signal when the mouse goes over the delegate, I have tried many "solutions" none has worked yet for me.

                        1 Reply Last reply
                        0
                        • VRoninV Offline
                          VRoninV Offline
                          VRonin
                          wrote on last edited by VRonin
                          #19

                          Sorry for the choppy response. Your delegate code is doing the right thing (just minor note it should handle QEvent::HoverEnter instead of QEvent::Enter), the problem is that hover events are not passed by the view to the delegate. You need to subclass your view and reimplement viewportEvent to something like: (warning: untested code)

                          class HoverDelegateView : public QTableView{
                              Q_OBJECT
                          #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                              Q_DISABLE_COPY_MOVE(HoverDelegateView)
                          #else
                              Q_DISABLE_COPY(HoverDelegateView)
                          #endif
                          public:
                              explicit HoverDelegateView(QWidget *parent = Q_NULLPTR)
                                  : QTableView(parent)
                              {}
                          protected:
                              bool viewportEvent(QEvent *event) Q_DECL_OVERRIDE
                              {
                                  switch (event->type()){
                                  case QEvent::HoverMove:
                                  case QEvent::HoverEnter:
                                  case QEvent::HoverLeave:{
                          #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
                                      QModelIndex index = indexAt(static_cast<QHoverEvent*>(event)->position().toPoint());
                                      QStyleOptionViewItem options;
                                      initViewItemOption(&options);
                          #else
                                      QModelIndex index = indexAt(static_cast<QHoverEvent*>(event)->pos());
                                      QStyleOptionViewItem options = viewOptions();
                          #endif
                                      QModelIndex buddy = model()->buddy(index);
                                      options.rect = visualRect(buddy);
                                      options.state |= (buddy == currentIndex() ? QStyle::State_HasFocus : QStyle::State_None);
                                      QAbstractItemDelegate *delegate = itemDelegate(index);
                                      delegate->editorEvent(event, model(), options, buddy);
                                      break;
                                  }
                                  default:
                                      break;
                                  }
                                  return QAbstractItemView::viewportEvent(event);
                              }
                          };
                          

                          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                          ~Napoleon Bonaparte

                          On a crusade to banish setIndexWidget() from the holy land of Qt

                          H 1 Reply Last reply
                          1
                          • VRoninV VRonin

                            Sorry for the choppy response. Your delegate code is doing the right thing (just minor note it should handle QEvent::HoverEnter instead of QEvent::Enter), the problem is that hover events are not passed by the view to the delegate. You need to subclass your view and reimplement viewportEvent to something like: (warning: untested code)

                            class HoverDelegateView : public QTableView{
                                Q_OBJECT
                            #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                                Q_DISABLE_COPY_MOVE(HoverDelegateView)
                            #else
                                Q_DISABLE_COPY(HoverDelegateView)
                            #endif
                            public:
                                explicit HoverDelegateView(QWidget *parent = Q_NULLPTR)
                                    : QTableView(parent)
                                {}
                            protected:
                                bool viewportEvent(QEvent *event) Q_DECL_OVERRIDE
                                {
                                    switch (event->type()){
                                    case QEvent::HoverMove:
                                    case QEvent::HoverEnter:
                                    case QEvent::HoverLeave:{
                            #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
                                        QModelIndex index = indexAt(static_cast<QHoverEvent*>(event)->position().toPoint());
                                        QStyleOptionViewItem options;
                                        initViewItemOption(&options);
                            #else
                                        QModelIndex index = indexAt(static_cast<QHoverEvent*>(event)->pos());
                                        QStyleOptionViewItem options = viewOptions();
                            #endif
                                        QModelIndex buddy = model()->buddy(index);
                                        options.rect = visualRect(buddy);
                                        options.state |= (buddy == currentIndex() ? QStyle::State_HasFocus : QStyle::State_None);
                                        QAbstractItemDelegate *delegate = itemDelegate(index);
                                        delegate->editorEvent(event, model(), options, buddy);
                                        break;
                                    }
                                    default:
                                        break;
                                    }
                                    return QAbstractItemView::viewportEvent(event);
                                }
                            };
                            
                            H Offline
                            H Offline
                            hbatalha
                            wrote on last edited by
                            #20

                            @VRonin I understood what you said, the concept behind it. In the code there are two undeclared identifiers: viewOptions and index though.

                            VRoninV 1 Reply Last reply
                            0
                            • H hbatalha

                              @VRonin I understood what you said, the concept behind it. In the code there are two undeclared identifiers: viewOptions and index though.

                              VRoninV Offline
                              VRoninV Offline
                              VRonin
                              wrote on last edited by
                              #21

                              @hbatalha said in Add widget right aligned to a QTableWidget cell:

                              @VRonin I understood what you said, the concept behind it. In the code there are two undeclared identifiers: viewOptions and index though.

                              Thanks, fixed those

                              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                              ~Napoleon Bonaparte

                              On a crusade to banish setIndexWidget() from the holy land of Qt

                              H 2 Replies Last reply
                              1
                              • H hbatalha

                                Also I would like have the button in the middle of the cell(top - bottom), this when set the size to (10,10)

                                VRoninV Offline
                                VRoninV Offline
                                VRonin
                                wrote on last edited by VRonin
                                #22

                                @hbatalha said in Add widget right aligned to a QTableWidget cell:

                                Also I would like have the button in the middle of the cell(top - bottom), this when set the size to (10,10)

                                Again this is managed by buttonRect, the 3rd argument to be precise:

                                virtual QRect buttonRect(const QStyleOptionViewItem &option) const{
                                    return QRect(option.rect.left()+option.rect.width()-10,option.rect.top()+qMax(0,(option.rect.height()-10)/2),10,10);
                                }
                                

                                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                ~Napoleon Bonaparte

                                On a crusade to banish setIndexWidget() from the holy land of Qt

                                H 1 Reply Last reply
                                0
                                • VRoninV VRonin

                                  @hbatalha said in Add widget right aligned to a QTableWidget cell:

                                  @VRonin I understood what you said, the concept behind it. In the code there are two undeclared identifiers: viewOptions and index though.

                                  Thanks, fixed those

                                  H Offline
                                  H Offline
                                  hbatalha
                                  wrote on last edited by
                                  #23

                                  @VRonin I will test the code and get back to you.

                                  1 Reply Last reply
                                  0
                                  • VRoninV VRonin

                                    @hbatalha said in Add widget right aligned to a QTableWidget cell:

                                    Also I would like have the button in the middle of the cell(top - bottom), this when set the size to (10,10)

                                    Again this is managed by buttonRect, the 3rd argument to be precise:

                                    virtual QRect buttonRect(const QStyleOptionViewItem &option) const{
                                        return QRect(option.rect.left()+option.rect.width()-10,option.rect.top()+qMax(0,(option.rect.height()-10)/2),10,10);
                                    }
                                    
                                    H Offline
                                    H Offline
                                    hbatalha
                                    wrote on last edited by
                                    #24

                                    @VRonin I figured that out.

                                    1 Reply Last reply
                                    0
                                    • VRoninV VRonin

                                      @hbatalha said in Add widget right aligned to a QTableWidget cell:

                                      @VRonin I understood what you said, the concept behind it. In the code there are two undeclared identifiers: viewOptions and index though.

                                      Thanks, fixed those

                                      H Offline
                                      H Offline
                                      hbatalha
                                      wrote on last edited by
                                      #25

                                      @VRonin I thought you edited the reply to fix the undeclared identifiers errors in the code but they are still there.

                                      JonBJ 1 Reply Last reply
                                      0
                                      • H hbatalha

                                        @VRonin I thought you edited the reply to fix the undeclared identifiers errors in the code but they are still there.

                                        JonBJ Offline
                                        JonBJ Offline
                                        JonB
                                        wrote on last edited by
                                        #26

                                        @hbatalha
                                        You wrote earlier

                                        In the code there are two undeclared identifiers: viewOptions and index though.

                                        Looking at those in @VRonin's code now they should be fine? If you have a compilation error show it.

                                        H 2 Replies Last reply
                                        0
                                        • JonBJ JonB

                                          @hbatalha
                                          You wrote earlier

                                          In the code there are two undeclared identifiers: viewOptions and index though.

                                          Looking at those in @VRonin's code now they should be fine? If you have a compilation error show it.

                                          H Offline
                                          H Offline
                                          hbatalha
                                          wrote on last edited by hbatalha
                                          #27
                                          This post is deleted!
                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved