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.0k 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.
  • 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
                                    • H Offline
                                      H Offline
                                      hbatalha
                                      wrote on last edited by
                                      #34

                                      Ok

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

                                      you should cast it to the correct type: QHoverEvent. Also me->pos() works in Qt5 but you need me->position() for Qt6

                                      Will do it.

                                      I have a question: in createEditor, I just deleted the two connect lines and signals are still being emitted. So what is the purpose of creating the MyButton object there?

                                      1 Reply Last reply
                                      0
                                      • VRoninV VRonin

                                        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

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

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

                                        Also me->pos() works in Qt5 but you need me->position() for Qt6

                                        here QRect::contains takes a QPoint but me->position is a QPointF, I will have to do some casting.

                                        Edit: I will just use QPointF::toPoint

                                        VRoninV 1 Reply Last reply
                                        0
                                        • H hbatalha

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

                                          Also me->pos() works in Qt5 but you need me->position() for Qt6

                                          here QRect::contains takes a QPoint but me->position is a QPointF, I will have to do some casting.

                                          Edit: I will just use QPointF::toPoint

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

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

                                          here QRect::contains takes a QPoint but me->position is a QPointF, I will have to do some casting.

                                          Just call .toPoint() see TableWidgetDelegate::viewportEvent

                                          I have a question: in createEditor, I just deleted the two connect lines and signals are still being emitted. So what is the purpose of creating the MyButton object there?

                                          Those 2 lines deal with when the user is actually editing. In my original example the delegate was the default editor (usually a lineedit) + a button on the side. The default editor is used to change the contents of the cell. If the user starts editing the cell (doubleclick by default) the editor will pop up and you'll see that clicking on the buttons will not do anything unless you have those 2 connects.
                                          In a nutshell we have to handle 2 cases: when the delegate is just painting and when the editor is presented to the user

                                          "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

                                          • Login

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