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.2k 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 hbatalha

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

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

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

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

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

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

    Can you show your code?

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

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

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

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

    H 1 Reply Last reply
    3
    • VRoninV VRonin

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

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

      Can you show your code?

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

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

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

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

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

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

      I Will try that, I am curious to see it

      Can you show your code?

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

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

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

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

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

        Also the button is still not clickable

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

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

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

          Then you can use it with something like:

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

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

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

          H 1 Reply Last reply
          2
          • H hbatalha

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

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

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

            I Will try that, I am curious to see it

            Can you show your code?

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

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

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

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

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

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

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

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

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

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

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

            1 Reply Last reply
            0
            • VRoninV VRonin

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

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

              Then you can use it with something like:

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

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

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

              but it is not working.

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

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

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

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

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

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

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

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

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

                    H 1 Reply Last reply
                    1
                    • VRoninV VRonin

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

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

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

                      VRoninV 1 Reply Last reply
                      0
                      • H hbatalha

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

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

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

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

                        Thanks, fixed those

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

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

                        H 2 Replies Last reply
                        1
                        • H hbatalha

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

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

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

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

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

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

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

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

                          H 1 Reply Last reply
                          0
                          • VRoninV VRonin

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

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

                            Thanks, fixed those

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

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

                            1 Reply Last reply
                            0
                            • VRoninV VRonin

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

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

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

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

                              @VRonin I figured that out.

                              1 Reply Last reply
                              0
                              • VRoninV VRonin

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

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

                                Thanks, fixed those

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

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

                                JonBJ 1 Reply Last reply
                                0
                                • H hbatalha

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

                                  JonBJ Online
                                  JonBJ Online
                                  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

                                          • Login

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