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 7.3k 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 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
                              • 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
                                #28

                                @JonB

                                10b05a11-55e7-482b-89bc-47cfbe8a827f-image.png

                                When I include it and tried to use it theses errors we thrown.

                                VRoninV 1 Reply Last reply
                                0
                                • H hbatalha

                                  @JonB

                                  10b05a11-55e7-482b-89bc-47cfbe8a827f-image.png

                                  When I include it and tried to use it theses errors we thrown.

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

                                  @hbatalha I edited my post above to take care of these issues

                                  "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 I edited my post above to take care of these issues

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

                                    @VRonin yeah it is compiling now but it's not emitting the HoverEnter signal unfortunately:
                                    buttondelegate.h

                                    #ifndef BUTTONDELEGATE_H
                                    #define BUTTONDELEGATE_H
                                    
                                    #include <QApplication>
                                    #include <QStyledItemDelegate>
                                    #include <QPushButton>
                                    #include <QMouseEvent>
                                    #include <QToolTip>
                                    #include <QPainter>
                                    #include <QPalette>
                                    #include <QTableWidget>
                                    
                                    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 ButtonDelegate : public QStyledItemDelegate
                                    {
                                        Q_OBJECT
                                    #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                                        Q_DISABLE_COPY_MOVE(ButtonDelegate)
                                    #else
                                        Q_DISABLE_COPY(ButtonDelegate)
                                    #endif
                                    public:
                                        explicit ButtonDelegate(QObject* parent)
                                            :QStyledItemDelegate(parent),
                                             tableWidget(qobject_cast<QTableWidget*>(parent))
                                        {
                                            mIsChecked = false;
                                            isDetailsButton = false;
                                            isEnabled = true;
                                            isHidden = false;
                                        }
                                        void update()
                                        {
                                            tableWidget->viewport()->update();
                                        }
                                        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
                                        {
                                            Q_ASSERT(index.isValid());
                                    
                                            bool shouldPaint = false;
                                            if(isDetailsButton)
                                            {
                                                if(index.column() == 0)
                                                    shouldPaint = true;
                                            }
                                            else
                                                shouldPaint = true;
                                    
                                            if(shouldPaint)
                                            {
                                                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);
                                    
                                                if(! isHidden)
                                                {
                                                    style->drawControl(QStyle::CE_PushButton, &buttonOption, painter, widget);
                                                }
                                            }
                                            else
                                                QStyledItemDelegate::paint(painter, option, index);
                                        }
                                        QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 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 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->setEnabled(false);
                                            myButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
                                            connect(myButton, &MyButton::clicked, this, &ButtonDelegate::clickedHelper);
                                            connect(myButton, &MyButton::mouseIn, this, &ButtonDelegate::mouseInHelper);
                                            return result;
                                        }
                                        void setEditorData(QWidget *editor, const QModelIndex &index) const 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 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 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 text() const
                                        {
                                            return m_buttonText;
                                        }
                                        void setText(const QString &newButtonText)
                                        {
                                            m_buttonText = newButtonText;
                                            update();
                                        }
                                        const QIcon &icon() const
                                        {
                                            return m_buttonIcon;
                                        }
                                        void setIcon(const QIcon &newButtonIcon)
                                        {
                                            m_buttonIcon = newButtonIcon;
                                            update();
                                        }
                                        void setChecked(bool checked)
                                        {
                                            mIsChecked = checked;
                                        }
                                        bool isChecked()
                                        {
                                            return mIsChecked;
                                        }
                                        void setToolTip(QString tooltip)
                                        {
                                            tooltipText = tooltip;
                                        }
                                        void setDetailsButton(bool idb)
                                        {
                                            isDetailsButton = idb;
                                            update();
                                        }
                                        void setEnabled(bool enabled)
                                        {
                                            isEnabled = enabled;
                                            update();
                                        }
                                        void setHidden(bool hide)
                                        {
                                            isHidden = hide;
                                            isEnabled = ! hide;
                                            update();
                                        }
                                        void click()
                                        {
                                            mIsChecked = ! mIsChecked;
                                            clickedHelper();
                                        }
                                    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) 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);
                                                    QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                                    if (me->button() == Qt::LeftButton)
                                                    {
                                                        mIsChecked = ! mIsChecked;
                                                        currentIndex = index;
                                                        clickedHelper();
                                                    }
                                                }
                                            }
                                    
                                            if (event->type() == QEvent::HoverEnter)
                                            {
                                                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;
                                    
                                            if(isEnabled)
                                                buttonOption.state = QStyle::State_Enabled;
                                            else
                                                buttonOption.state &= ~QStyle::State_Enabled;
                                    
                                            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));
                                    
                                            QRect r = option.rect;
                                            int x = isDetailsButton ? (r.left()+ r.width() - 10) : (r.center().x() - 6);
                                            int y = isDetailsButton ? r.top() : r.top() + 10;
                                            int s = isDetailsButton ? 10 : 1;
                                    
                                            return QRect(x, y, s, s);
                                        }
                                        virtual bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index) override
                                        {
                                            if( !event || !view )
                                                return false;
                                    
                                            if( event->type() == QEvent::ToolTip )
                                            {
                                                QVariant tooltip = index.data( Qt::DisplayRole );
                                                if( QApplication::keyboardModifiers() == Qt::AltModifier )
                                                {
                                                    QToolTip::showText( event->globalPos(), tooltipText);
                                                }
                                                else
                                                {
                                                    QToolTip::showText( event->globalPos(), tooltipText);
                                                }
                                    
                                                if( !QStyledItemDelegate::helpEvent( event, view, option, index ) )
                                                    QToolTip::hideText();
                                                return true;
                                            }
                                    
                                            return QStyledItemDelegate::helpEvent( event, view, option, index );
                                        }
                                    private:
                                        mutable QModelIndex currentIndex;
                                        QPainter* mPainter;
                                        QString m_buttonText;
                                        QIcon m_buttonIcon;
                                        bool mIsChecked;
                                        bool isDetailsButton;
                                        bool isEnabled;
                                        bool isHidden;
                                        QString tooltipText;
                                        QTableWidget* tableWidget;
                                    
                                        void clickedHelper()
                                        {
                                            clicked(currentIndex);
                                        }
                                        void mouseInHelper()
                                        {
                                            mouseIn(currentIndex);
                                        }
                                    };
                                    #endif // BUTTONDELEGATE_H
                                    

                                    tableWidgetDelegate.h

                                    #ifndef TABLEWIDGETDELEGATE_H
                                    #define TABLEWIDGETDELEGATE_H
                                    
                                    #include <QTableWidget>
                                    #include <QEvent>
                                    #include <QModelIndex>
                                    #include <QStyleOptionViewItem>
                                    #include <QHoverEvent>
                                    
                                    class TableWidgetDelegate : public QTableWidget
                                    {
                                        Q_OBJECT
                                    #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                                        Q_DISABLE_COPY_MOVE(TableWidgetDelegate)
                                    #else
                                        Q_DISABLE_COPY(TableWidgetDelegate)
                                    #endif
                                    public:
                                        explicit TableWidgetDelegate(QWidget *parent = Q_NULLPTR)
                                            : QTableWidget(parent)
                                        {}
                                    protected:
                                        bool viewportEvent(QEvent *event) override
                                        {
                                            switch (event->type())
                                            {
                                            case QEvent::HoverMove:
                                            case QEvent::HoverEnter:
                                            case QEvent::HoverLeave:
                                            case QEvent::MouseMove:
                                            {
                                    #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
                                                qDebug() << "QTableWidget -- viewport";
                                    
                                                QModelIndex buddy = model()->buddy(index);
                                                options.rect = visualRect(buddy);
                                                options.state |= (buddy == currentIndex() ? QStyle::State_HasFocus : QStyle::State_None);
                                                QAbstractItemDelegate *delegate = itemDelegateForIndex(index);
                                                delegate->editorEvent(event, model(), options, buddy);
                                                break;
                                            }
                                            default:
                                                break;
                                            }
                                            return QAbstractItemView::viewportEvent(event);
                                        }
                                    };
                                    #endif // TABLEWIDGETDELEGATE_H
                                    
                                    
                                    1 Reply Last reply
                                    0
                                    • VRoninV Offline
                                      VRoninV Offline
                                      VRonin
                                      wrote on last edited by
                                      #31

                                      Tested now:
                                      tablewidgetdelegate.h

                                      #ifndef TABLEWIDGETDELEGATE_H
                                      #define TABLEWIDGETDELEGATE_H
                                      
                                      #include <QTableWidget>
                                      #include <QEvent>
                                      #include <QModelIndex>
                                      #include <QStyleOptionViewItem>
                                      #include <QHoverEvent>
                                      
                                      class TableWidgetDelegate : public QTableWidget
                                      {
                                          Q_OBJECT
                                      #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                                          Q_DISABLE_COPY_MOVE(TableWidgetDelegate)
                                      #else
                                          Q_DISABLE_COPY(TableWidgetDelegate)
                                      #endif
                                      public:
                                          explicit TableWidgetDelegate(QWidget *parent = Q_NULLPTR)
                                              : QTableWidget(parent)
                                          {
                                              viewport()->setAttribute(Qt::WA_Hover,true);
                                          }
                                      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);
                                                  QAbstractItemDelegate *delegate = itemDelegateForIndex(index);
                                      #else
                                                  QModelIndex index = indexAt(static_cast<QHoverEvent*>(event)->pos());
                                                  QStyleOptionViewItem options = viewOptions();
                                                  QAbstractItemDelegate *delegate = itemDelegate(index);
                                      #endif
                                                  if(delegate){
                                                      QModelIndex buddy = model()->buddy(index);
                                                      options.rect = visualRect(buddy);
                                                      options.state |= (buddy == currentIndex() ? QStyle::State_HasFocus : QStyle::State_None);
                                                      delegate->editorEvent(event, model(), options, buddy);
                                                  }
                                                  break;
                                              }
                                              default:
                                                  break;
                                              }
                                              return QAbstractItemView::viewportEvent(event);
                                          }
                                      };
                                      #endif // TABLEWIDGETDELEGATE_H
                                      

                                      buttondelegate.h

                                      #ifndef BUTTONDELEGATE_H
                                      #define BUTTONDELEGATE_H
                                      
                                      #include <QApplication>
                                      #include <QStyledItemDelegate>
                                      #include <QPushButton>
                                      #include <QMouseEvent>
                                      #include <QToolTip>
                                      #include <QPainter>
                                      #include <QPalette>
                                      #include <QTableWidget>
                                      #include "mybutton.h"
                                      
                                      class ButtonDelegate : public QStyledItemDelegate
                                      {
                                          Q_OBJECT
                                      #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                                          Q_DISABLE_COPY_MOVE(ButtonDelegate)
                                      #else
                                          Q_DISABLE_COPY(ButtonDelegate)
                                      #endif
                                      public:
                                          explicit ButtonDelegate(QObject* parent)
                                              :QStyledItemDelegate(parent),
                                               tableWidget(qobject_cast<QTableWidget*>(parent))
                                          {
                                              mIsChecked = false;
                                              isDetailsButton = false;
                                              isEnabled = true;
                                              isHidden = false;
                                          }
                                          void update()
                                          {
                                              tableWidget->viewport()->update();
                                          }
                                          void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                                          {
                                              Q_ASSERT(index.isValid());
                                      
                                              bool shouldPaint = false;
                                              if(isDetailsButton)
                                              {
                                                  if(index.column() == 0)
                                                      shouldPaint = true;
                                              }
                                              else
                                                  shouldPaint = true;
                                      
                                              if(shouldPaint)
                                              {
                                                  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);
                                      
                                                  if(! isHidden)
                                                  {
                                                      style->drawControl(QStyle::CE_PushButton, &buttonOption, painter, widget);
                                                  }
                                              }
                                              else
                                                  QStyledItemDelegate::paint(painter, option, index);
                                          }
                                          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->setEnabled(false);
                                              myButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
                                              connect(myButton, &MyButton::clicked, this, &ButtonDelegate::clickedHelper);
                                              connect(myButton, &MyButton::mouseIn, this, &ButtonDelegate::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 text() const
                                          {
                                              return m_buttonText;
                                          }
                                          void setText(const QString &newButtonText)
                                          {
                                              m_buttonText = newButtonText;
                                              update();
                                          }
                                          const QIcon &icon() const
                                          {
                                              return m_buttonIcon;
                                          }
                                          void setIcon(const QIcon &newButtonIcon)
                                          {
                                              m_buttonIcon = newButtonIcon;
                                              update();
                                          }
                                          void setChecked(bool checked)
                                          {
                                              mIsChecked = checked;
                                          }
                                          bool isChecked()
                                          {
                                              return mIsChecked;
                                          }
                                          void setToolTip(QString tooltip)
                                          {
                                              tooltipText = tooltip;
                                          }
                                          void setDetailsButton(bool idb)
                                          {
                                              isDetailsButton = idb;
                                              update();
                                          }
                                          void setEnabled(bool enabled)
                                          {
                                              isEnabled = enabled;
                                              update();
                                          }
                                          void setHidden(bool hide)
                                          {
                                              isHidden = hide;
                                              isEnabled = ! hide;
                                              update();
                                          }
                                          void click()
                                          {
                                              mIsChecked = ! mIsChecked;
                                              clickedHelper();
                                          }
                                      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) override
                                          {
                                              Q_ASSERT(event);
                                              Q_ASSERT(model);
                                              Qt::ItemFlags flags = model->flags(index);
                                              if ((option.state & QStyle::State_Enabled) && (flags & Qt::ItemIsEnabled))
                                              {
                                                  switch (event->type()){
                                                  case QEvent::MouseButtonRelease:{
                                                      QStyleOptionViewItem viewOpt(option);
                                                      initStyleOption(&viewOpt, index);
                                                      QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                                      if (me->button() == Qt::LeftButton)
                                                      {
                                                          mIsChecked = ! mIsChecked;
                                                          currentIndex = index;
                                                          clickedHelper();
                                                      }
                                                  }
                                                      break;
                                                  case QEvent::HoverMove:
                                                  case QEvent::HoverEnter:
                                                  case QEvent::HoverLeave:
                                                      if(index!=currentIndex){
                                                          currentIndex = index;
                                                          if(index.isValid())
                                                              mouseInHelper();
                                                      }
                                                      break;
                                                  default:
                                                      break;
                                                  }
                                              }
                                              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;
                                      
                                              if(isEnabled)
                                                  buttonOption.state = QStyle::State_Enabled;
                                              else
                                                  buttonOption.state &= ~QStyle::State_Enabled;
                                      
                                              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()));
                                      /*
                                              QRect r = option.rect;
                                              int x = isDetailsButton ? (r.left()+ r.width() - 10) : (r.center().x() - 6);
                                              int y = isDetailsButton ? r.top() : r.top() + 10;
                                              int s = isDetailsButton ? 10 : 1;
                                      
                                              return QRect(x, y, s, s);
                                              */
                                          }
                                          virtual bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index) override
                                          {
                                              if( !event || !view )
                                                  return false;
                                      
                                              if( event->type() == QEvent::ToolTip )
                                              {
                                                  QVariant tooltip = index.data( Qt::DisplayRole );
                                                  if( QApplication::keyboardModifiers() == Qt::AltModifier )
                                                  {
                                                      QToolTip::showText( event->globalPos(), tooltipText);
                                                  }
                                                  else
                                                  {
                                                      QToolTip::showText( event->globalPos(), tooltipText);
                                                  }
                                      
                                                  if( !QStyledItemDelegate::helpEvent( event, view, option, index ) )
                                                      QToolTip::hideText();
                                                  return true;
                                              }
                                      
                                              return QStyledItemDelegate::helpEvent( event, view, option, index );
                                          }
                                      private:
                                          mutable QModelIndex currentIndex;
                                          QPainter* mPainter;
                                          QString m_buttonText;
                                          QIcon m_buttonIcon;
                                          bool mIsChecked;
                                          bool isDetailsButton;
                                          bool isEnabled;
                                          bool isHidden;
                                          QString tooltipText;
                                          QTableWidget* tableWidget;
                                      
                                          void clickedHelper()
                                          {
                                              clicked(currentIndex);
                                          }
                                          void mouseInHelper()
                                          {
                                              mouseIn(currentIndex);
                                          }
                                      };
                                      #endif // BUTTONDELEGATE_H
                                      

                                      mybutton.h

                                      #ifndef MYBUTTON_H
                                      #define MYBUTTON_H
                                      #include <QPushButton>
                                      class MyButton : public QPushButton
                                      {
                                          Q_OBJECT
                                      #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                                          Q_DISABLE_COPY_MOVE(MyButton)
                                      #else
                                          Q_DISABLE_COPY(MyButton)
                                      #endif
                                      public:
                                          MyButton(QWidget* parent = 0) : QPushButton(parent) {}
                                          ~MyButton() {};
                                      
                                      signals:
                                          void mouseIn();
                                      
                                      protected:
                                      #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
                                          void enterEvent(QEnterEvent*) Q_DECL_OVERRIDE
                                      #else
                                          void enterEvent(QEvent*) Q_DECL_OVERRIDE
                                      #endif
                                          {
                                              emit mouseIn();
                                          }
                                      };
                                      #endif // MYBUTTON_H
                                      

                                      main.cpp

                                      #include <QApplication>
                                      #include "buttondelegate.h"
                                      #include <QModelIndex>
                                      #include "tablewidgetdelegate.h"
                                      #include <QDebug>
                                      
                                      int main(int argc, char *argv[])
                                      {
                                          QApplication app(argc,argv);
                                          TableWidgetDelegate wid;
                                          wid.setColumnCount(2);
                                          wid.setRowCount(2);
                                          ButtonDelegate *butDelegate = new ButtonDelegate(&wid);
                                          butDelegate->setText("Test");
                                          QPixmap bluePixmap(20,20);
                                          bluePixmap.fill(Qt::blue);
                                          QIcon blueIcon;
                                          blueIcon.addPixmap(bluePixmap);
                                          butDelegate->setIcon(blueIcon);
                                          QObject::connect(butDelegate,&ButtonDelegate::clicked,[](const QModelIndex& index){qDebug() << "Clicked " << index;});
                                          QObject::connect(butDelegate,&ButtonDelegate::mouseIn,[](const QModelIndex& index){qDebug() << "MouseIn " << 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
                                      1
                                      • VRoninV VRonin

                                        Tested now:
                                        tablewidgetdelegate.h

                                        #ifndef TABLEWIDGETDELEGATE_H
                                        #define TABLEWIDGETDELEGATE_H
                                        
                                        #include <QTableWidget>
                                        #include <QEvent>
                                        #include <QModelIndex>
                                        #include <QStyleOptionViewItem>
                                        #include <QHoverEvent>
                                        
                                        class TableWidgetDelegate : public QTableWidget
                                        {
                                            Q_OBJECT
                                        #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                                            Q_DISABLE_COPY_MOVE(TableWidgetDelegate)
                                        #else
                                            Q_DISABLE_COPY(TableWidgetDelegate)
                                        #endif
                                        public:
                                            explicit TableWidgetDelegate(QWidget *parent = Q_NULLPTR)
                                                : QTableWidget(parent)
                                            {
                                                viewport()->setAttribute(Qt::WA_Hover,true);
                                            }
                                        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);
                                                    QAbstractItemDelegate *delegate = itemDelegateForIndex(index);
                                        #else
                                                    QModelIndex index = indexAt(static_cast<QHoverEvent*>(event)->pos());
                                                    QStyleOptionViewItem options = viewOptions();
                                                    QAbstractItemDelegate *delegate = itemDelegate(index);
                                        #endif
                                                    if(delegate){
                                                        QModelIndex buddy = model()->buddy(index);
                                                        options.rect = visualRect(buddy);
                                                        options.state |= (buddy == currentIndex() ? QStyle::State_HasFocus : QStyle::State_None);
                                                        delegate->editorEvent(event, model(), options, buddy);
                                                    }
                                                    break;
                                                }
                                                default:
                                                    break;
                                                }
                                                return QAbstractItemView::viewportEvent(event);
                                            }
                                        };
                                        #endif // TABLEWIDGETDELEGATE_H
                                        

                                        buttondelegate.h

                                        #ifndef BUTTONDELEGATE_H
                                        #define BUTTONDELEGATE_H
                                        
                                        #include <QApplication>
                                        #include <QStyledItemDelegate>
                                        #include <QPushButton>
                                        #include <QMouseEvent>
                                        #include <QToolTip>
                                        #include <QPainter>
                                        #include <QPalette>
                                        #include <QTableWidget>
                                        #include "mybutton.h"
                                        
                                        class ButtonDelegate : public QStyledItemDelegate
                                        {
                                            Q_OBJECT
                                        #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                                            Q_DISABLE_COPY_MOVE(ButtonDelegate)
                                        #else
                                            Q_DISABLE_COPY(ButtonDelegate)
                                        #endif
                                        public:
                                            explicit ButtonDelegate(QObject* parent)
                                                :QStyledItemDelegate(parent),
                                                 tableWidget(qobject_cast<QTableWidget*>(parent))
                                            {
                                                mIsChecked = false;
                                                isDetailsButton = false;
                                                isEnabled = true;
                                                isHidden = false;
                                            }
                                            void update()
                                            {
                                                tableWidget->viewport()->update();
                                            }
                                            void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
                                            {
                                                Q_ASSERT(index.isValid());
                                        
                                                bool shouldPaint = false;
                                                if(isDetailsButton)
                                                {
                                                    if(index.column() == 0)
                                                        shouldPaint = true;
                                                }
                                                else
                                                    shouldPaint = true;
                                        
                                                if(shouldPaint)
                                                {
                                                    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);
                                        
                                                    if(! isHidden)
                                                    {
                                                        style->drawControl(QStyle::CE_PushButton, &buttonOption, painter, widget);
                                                    }
                                                }
                                                else
                                                    QStyledItemDelegate::paint(painter, option, index);
                                            }
                                            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->setEnabled(false);
                                                myButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
                                                connect(myButton, &MyButton::clicked, this, &ButtonDelegate::clickedHelper);
                                                connect(myButton, &MyButton::mouseIn, this, &ButtonDelegate::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 text() const
                                            {
                                                return m_buttonText;
                                            }
                                            void setText(const QString &newButtonText)
                                            {
                                                m_buttonText = newButtonText;
                                                update();
                                            }
                                            const QIcon &icon() const
                                            {
                                                return m_buttonIcon;
                                            }
                                            void setIcon(const QIcon &newButtonIcon)
                                            {
                                                m_buttonIcon = newButtonIcon;
                                                update();
                                            }
                                            void setChecked(bool checked)
                                            {
                                                mIsChecked = checked;
                                            }
                                            bool isChecked()
                                            {
                                                return mIsChecked;
                                            }
                                            void setToolTip(QString tooltip)
                                            {
                                                tooltipText = tooltip;
                                            }
                                            void setDetailsButton(bool idb)
                                            {
                                                isDetailsButton = idb;
                                                update();
                                            }
                                            void setEnabled(bool enabled)
                                            {
                                                isEnabled = enabled;
                                                update();
                                            }
                                            void setHidden(bool hide)
                                            {
                                                isHidden = hide;
                                                isEnabled = ! hide;
                                                update();
                                            }
                                            void click()
                                            {
                                                mIsChecked = ! mIsChecked;
                                                clickedHelper();
                                            }
                                        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) override
                                            {
                                                Q_ASSERT(event);
                                                Q_ASSERT(model);
                                                Qt::ItemFlags flags = model->flags(index);
                                                if ((option.state & QStyle::State_Enabled) && (flags & Qt::ItemIsEnabled))
                                                {
                                                    switch (event->type()){
                                                    case QEvent::MouseButtonRelease:{
                                                        QStyleOptionViewItem viewOpt(option);
                                                        initStyleOption(&viewOpt, index);
                                                        QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                                        if (me->button() == Qt::LeftButton)
                                                        {
                                                            mIsChecked = ! mIsChecked;
                                                            currentIndex = index;
                                                            clickedHelper();
                                                        }
                                                    }
                                                        break;
                                                    case QEvent::HoverMove:
                                                    case QEvent::HoverEnter:
                                                    case QEvent::HoverLeave:
                                                        if(index!=currentIndex){
                                                            currentIndex = index;
                                                            if(index.isValid())
                                                                mouseInHelper();
                                                        }
                                                        break;
                                                    default:
                                                        break;
                                                    }
                                                }
                                                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;
                                        
                                                if(isEnabled)
                                                    buttonOption.state = QStyle::State_Enabled;
                                                else
                                                    buttonOption.state &= ~QStyle::State_Enabled;
                                        
                                                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()));
                                        /*
                                                QRect r = option.rect;
                                                int x = isDetailsButton ? (r.left()+ r.width() - 10) : (r.center().x() - 6);
                                                int y = isDetailsButton ? r.top() : r.top() + 10;
                                                int s = isDetailsButton ? 10 : 1;
                                        
                                                return QRect(x, y, s, s);
                                                */
                                            }
                                            virtual bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index) override
                                            {
                                                if( !event || !view )
                                                    return false;
                                        
                                                if( event->type() == QEvent::ToolTip )
                                                {
                                                    QVariant tooltip = index.data( Qt::DisplayRole );
                                                    if( QApplication::keyboardModifiers() == Qt::AltModifier )
                                                    {
                                                        QToolTip::showText( event->globalPos(), tooltipText);
                                                    }
                                                    else
                                                    {
                                                        QToolTip::showText( event->globalPos(), tooltipText);
                                                    }
                                        
                                                    if( !QStyledItemDelegate::helpEvent( event, view, option, index ) )
                                                        QToolTip::hideText();
                                                    return true;
                                                }
                                        
                                                return QStyledItemDelegate::helpEvent( event, view, option, index );
                                            }
                                        private:
                                            mutable QModelIndex currentIndex;
                                            QPainter* mPainter;
                                            QString m_buttonText;
                                            QIcon m_buttonIcon;
                                            bool mIsChecked;
                                            bool isDetailsButton;
                                            bool isEnabled;
                                            bool isHidden;
                                            QString tooltipText;
                                            QTableWidget* tableWidget;
                                        
                                            void clickedHelper()
                                            {
                                                clicked(currentIndex);
                                            }
                                            void mouseInHelper()
                                            {
                                                mouseIn(currentIndex);
                                            }
                                        };
                                        #endif // BUTTONDELEGATE_H
                                        

                                        mybutton.h

                                        #ifndef MYBUTTON_H
                                        #define MYBUTTON_H
                                        #include <QPushButton>
                                        class MyButton : public QPushButton
                                        {
                                            Q_OBJECT
                                        #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
                                            Q_DISABLE_COPY_MOVE(MyButton)
                                        #else
                                            Q_DISABLE_COPY(MyButton)
                                        #endif
                                        public:
                                            MyButton(QWidget* parent = 0) : QPushButton(parent) {}
                                            ~MyButton() {};
                                        
                                        signals:
                                            void mouseIn();
                                        
                                        protected:
                                        #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
                                            void enterEvent(QEnterEvent*) Q_DECL_OVERRIDE
                                        #else
                                            void enterEvent(QEvent*) Q_DECL_OVERRIDE
                                        #endif
                                            {
                                                emit mouseIn();
                                            }
                                        };
                                        #endif // MYBUTTON_H
                                        

                                        main.cpp

                                        #include <QApplication>
                                        #include "buttondelegate.h"
                                        #include <QModelIndex>
                                        #include "tablewidgetdelegate.h"
                                        #include <QDebug>
                                        
                                        int main(int argc, char *argv[])
                                        {
                                            QApplication app(argc,argv);
                                            TableWidgetDelegate wid;
                                            wid.setColumnCount(2);
                                            wid.setRowCount(2);
                                            ButtonDelegate *butDelegate = new ButtonDelegate(&wid);
                                            butDelegate->setText("Test");
                                            QPixmap bluePixmap(20,20);
                                            bluePixmap.fill(Qt::blue);
                                            QIcon blueIcon;
                                            blueIcon.addPixmap(bluePixmap);
                                            butDelegate->setIcon(blueIcon);
                                            QObject::connect(butDelegate,&ButtonDelegate::clicked,[](const QModelIndex& index){qDebug() << "Clicked " << index;});
                                            QObject::connect(butDelegate,&ButtonDelegate::mouseIn,[](const QModelIndex& index){qDebug() << "MouseIn " << index;});
                                            wid.setItemDelegate(butDelegate);
                                            wid.show();
                                            return app.exec();
                                        }
                                        
                                        H Offline
                                        H Offline
                                        hbatalha
                                        wrote on last edited by hbatalha
                                        #32

                                        @VRonin Working perfectly, can't thank you enough. I made some changes in the buttondelegate.h's editorEvent function to better suit my needs:

                                            bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override
                                            {
                                                Q_ASSERT(event);
                                                Q_ASSERT(model);
                                                Qt::ItemFlags flags = model->flags(index);
                                                if ((option.state & QStyle::State_Enabled) && (flags & Qt::ItemIsEnabled))
                                                {
                                                    switch (event->type())
                                                    {
                                                    case QEvent::MouseButtonRelease:
                                                    {
                                                        QStyleOptionViewItem viewOpt(option);
                                                        initStyleOption(&viewOpt, index);
                                                        QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                                        if (me->button() == Qt::LeftButton)
                                                        {
                                                            mIsChecked = ! mIsChecked;
                                                            currentIndex = index;
                                                            clickedHelper();
                                                        }
                                                    }
                                                    break;
                                                    case QEvent::HoverMove:
                                                    case QEvent::HoverEnter:
                                                    {
                                                        QStyleOptionViewItem viewOpt(option);
                                                        const QRect butRect = buttonRect(viewOpt);
                                                        QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                        
                                                        currentIndex = index;
                                                        if(index.isValid() && butRect.contains(me->pos()))
                                                            mouseInHelper();
                                                    }
                                                    break;
                                                    default:
                                                        break;
                                                    }
                                                }
                                                return QStyledItemDelegate::editorEvent(event,model,option,index);
                                            }
                                        
                                        VRoninV 1 Reply Last reply
                                        0
                                        • H hbatalha

                                          @VRonin Working perfectly, can't thank you enough. I made some changes in the buttondelegate.h's editorEvent function to better suit my needs:

                                              bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override
                                              {
                                                  Q_ASSERT(event);
                                                  Q_ASSERT(model);
                                                  Qt::ItemFlags flags = model->flags(index);
                                                  if ((option.state & QStyle::State_Enabled) && (flags & Qt::ItemIsEnabled))
                                                  {
                                                      switch (event->type())
                                                      {
                                                      case QEvent::MouseButtonRelease:
                                                      {
                                                          QStyleOptionViewItem viewOpt(option);
                                                          initStyleOption(&viewOpt, index);
                                                          QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                                          if (me->button() == Qt::LeftButton)
                                                          {
                                                              mIsChecked = ! mIsChecked;
                                                              currentIndex = index;
                                                              clickedHelper();
                                                          }
                                                      }
                                                      break;
                                                      case QEvent::HoverMove:
                                                      case QEvent::HoverEnter:
                                                      {
                                                          QStyleOptionViewItem viewOpt(option);
                                                          const QRect butRect = buttonRect(viewOpt);
                                                          QMouseEvent *me = static_cast<QMouseEvent*>(event);
                                          
                                                          currentIndex = index;
                                                          if(index.isValid() && butRect.contains(me->pos()))
                                                              mouseInHelper();
                                                      }
                                                      break;
                                                      default:
                                                          break;
                                                      }
                                                  }
                                                  return QStyledItemDelegate::editorEvent(event,model,option,index);
                                              }
                                          
                                          VRoninV Offline
                                          VRoninV Offline
                                          VRonin
                                          wrote on last edited by VRonin
                                          #33

                                          I'm surprised QMouseEvent *me = static_cast<QMouseEvent*>(event); under case QEvent::HoverMove: case QEvent::HoverEnter: works. if it does is just through some compiler magic. you should cast it to the correct type: QHoverEvent. Also me->pos() works in Qt5 but you need me->position() for Qt6

                                          "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

                                          • Login

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