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

Add widget right aligned to a QTableWidget cell

Scheduled Pinned Locked Moved Solved General and Desktop
46 Posts 4 Posters 6.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    hbatalha
    wrote on last edited by
    #1

    I want to add a widget(QPushButton) at the end of a QTableWidget cell.
    I know there's QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget) but it inserts the widget at the beginning of the cell. I want to insert a widget at end.

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

      Tested now:
      tablewidgetdelegate.h

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

      buttondelegate.h

      #ifndef BUTTONDELEGATE_H
      #define BUTTONDELEGATE_H
      
      #include <QApplication>
      #include <QStyledItemDelegate>
      #include <QPushButton>
      #include <QMouseEvent>
      #include <QToolTip>
      #include <QPainter>
      #include <QPalette>
      #include <QTableWidget>
      #include "mybutton.h"
      
      class ButtonDelegate : public QStyledItemDelegate
      {
          Q_OBJECT
      #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
          Q_DISABLE_COPY_MOVE(ButtonDelegate)
      #else
          Q_DISABLE_COPY(ButtonDelegate)
      #endif
      public:
          explicit ButtonDelegate(QObject* parent)
              :QStyledItemDelegate(parent),
               tableWidget(qobject_cast<QTableWidget*>(parent))
          {
              mIsChecked = false;
              isDetailsButton = false;
              isEnabled = true;
              isHidden = false;
          }
          void update()
          {
              tableWidget->viewport()->update();
          }
          void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
          {
              Q_ASSERT(index.isValid());
      
              bool shouldPaint = false;
              if(isDetailsButton)
              {
                  if(index.column() == 0)
                      shouldPaint = true;
              }
              else
                  shouldPaint = true;
      
              if(shouldPaint)
              {
                  QStyleOptionViewItem opt = option;
                  initStyleOption(&opt, index);
                  const QWidget *widget = option.widget;
      
                  QStyle *style = widget ? widget->style() : QApplication::style();
                  style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
                  QStyleOptionButton buttonOption = buttonOptions(opt);
      
                  if(! isHidden)
                  {
                      style->drawControl(QStyle::CE_PushButton, &buttonOption, painter, widget);
                  }
              }
              else
                  QStyledItemDelegate::paint(painter, option, index);
          }
          QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
          {
              QStyleOptionViewItem opt = option;
              initStyleOption(&opt, index);
              const QSize baseSize = QStyledItemDelegate::sizeHint(option,index);
              const QRect butRect = buttonRect(opt);
              return QSize(baseSize.width()+butRect.width(),qMax(butRect.height(),baseSize.height()));
          }
          QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
          {
              QWidget* result = new QWidget(parent);
              result->setGeometry(option.rect);
              QWidget* baseEditor = QStyledItemDelegate::createEditor(result,option,index);
              result->setFocusProxy(baseEditor);
              QStyleOptionViewItem opt = option;
              initStyleOption(&opt, index);
              const QRect butRect = buttonRect(opt);
              baseEditor->setObjectName("baseEditor");
              baseEditor->setGeometry(0,0,opt.rect.width()-butRect.width(),opt.rect.height());
              MyButton* myButton = new MyButton(result);
              myButton->setObjectName("myButton");
              myButton->setText(m_buttonText);
              myButton->setIcon(m_buttonIcon);
              myButton->setEnabled(false);
              myButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
              connect(myButton, &MyButton::clicked, this, &ButtonDelegate::clickedHelper);
              connect(myButton, &MyButton::mouseIn, this, &ButtonDelegate::mouseInHelper);
              return result;
          }
          void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE
          {
              currentIndex = index;
              QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
              Q_ASSERT(baseEditor);
              QStyledItemDelegate::setEditorData(baseEditor,index);
          }
          void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE
          {
              QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
              Q_ASSERT(baseEditor);
              QStyledItemDelegate::setModelData(baseEditor,model,index);
          }
          void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE
          {
              QStyleOptionViewItem opt = option;
              initStyleOption(&opt, index);
              editor->setGeometry(opt.rect);
              const QRect butRect = buttonRect(opt);
              QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor");
              Q_ASSERT(baseEditor);
              baseEditor->setGeometry(0,0,opt.rect.width()-butRect.width(),opt.rect.height());
              QWidget* myButton = editor->findChild<QWidget*>("myButton");
              Q_ASSERT(myButton);
              myButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height());
          }
          const QString text() const
          {
              return m_buttonText;
          }
          void setText(const QString &newButtonText)
          {
              m_buttonText = newButtonText;
              update();
          }
          const QIcon &icon() const
          {
              return m_buttonIcon;
          }
          void setIcon(const QIcon &newButtonIcon)
          {
              m_buttonIcon = newButtonIcon;
              update();
          }
          void setChecked(bool checked)
          {
              mIsChecked = checked;
          }
          bool isChecked()
          {
              return mIsChecked;
          }
          void setToolTip(QString tooltip)
          {
              tooltipText = tooltip;
          }
          void setDetailsButton(bool idb)
          {
              isDetailsButton = idb;
              update();
          }
          void setEnabled(bool enabled)
          {
              isEnabled = enabled;
              update();
          }
          void setHidden(bool hide)
          {
              isHidden = hide;
              isEnabled = ! hide;
              update();
          }
          void click()
          {
              mIsChecked = ! mIsChecked;
              clickedHelper();
          }
      Q_SIGNALS:
          void clicked(const QModelIndex &index);
          void mouseIn(const QModelIndex &index);
      protected:
          bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override
          {
              Q_ASSERT(event);
              Q_ASSERT(model);
              Qt::ItemFlags flags = model->flags(index);
              if ((option.state & QStyle::State_Enabled) && (flags & Qt::ItemIsEnabled))
              {
                  switch (event->type()){
                  case QEvent::MouseButtonRelease:{
                      QStyleOptionViewItem viewOpt(option);
                      initStyleOption(&viewOpt, index);
                      QMouseEvent *me = static_cast<QMouseEvent*>(event);
                      if (me->button() == Qt::LeftButton)
                      {
                          mIsChecked = ! mIsChecked;
                          currentIndex = index;
                          clickedHelper();
                      }
                  }
                      break;
                  case QEvent::HoverMove:
                  case QEvent::HoverEnter:
                  case QEvent::HoverLeave:
                      if(index!=currentIndex){
                          currentIndex = index;
                          if(index.isValid())
                              mouseInHelper();
                      }
                      break;
                  default:
                      break;
                  }
              }
              return QStyledItemDelegate::editorEvent(event,model,option,index);
          }
          virtual QStyleOptionButton buttonOptions(const QStyleOptionViewItem &option, bool skipRct=false) const
          {
              const QWidget *widget = option.widget;
              QStyle *style = widget ? widget->style() : QApplication::style();
              int buttonIconSize = style->pixelMetric(QStyle::PM_ButtonIconSize, 0, widget);
              QStyleOptionButton buttonOption;
              buttonOption.text = m_buttonText;
              buttonOption.icon = m_buttonIcon;
              buttonOption.iconSize = (QSize(buttonIconSize,buttonIconSize));
              buttonOption.rect = skipRct ? QRect() : buttonRect(option);
              buttonOption.features = QStyleOptionButton::None;
              buttonOption.direction = option.direction;
              buttonOption.fontMetrics = option.fontMetrics;
              buttonOption.palette = option.palette;
              buttonOption.styleObject = option.styleObject;
      
              if(isEnabled)
                  buttonOption.state = QStyle::State_Enabled;
              else
                  buttonOption.state &= ~QStyle::State_Enabled;
      
              return buttonOption;
          }
          virtual QRect buttonRect(const QStyleOptionViewItem &option) const
          {
              const QStyleOptionButton buttonOption = buttonOptions(option, true);
              const QWidget *widget = option.widget;
              QStyle *style = widget ? widget->style() : QApplication::style();
              QSize buttonSize = style->sizeFromContents(QStyle::CT_PushButton, &buttonOption, QSize(), widget);
              buttonSize.setWidth(qMin(buttonSize.width(),option.rect.width()/2));
              return QRect(option.rect.left()+option.rect.width()-buttonSize.width(),option.rect.top(),buttonSize.width(),qMax(buttonSize.height(),option.rect.height()));
      /*
              QRect r = option.rect;
              int x = isDetailsButton ? (r.left()+ r.width() - 10) : (r.center().x() - 6);
              int y = isDetailsButton ? r.top() : r.top() + 10;
              int s = isDetailsButton ? 10 : 1;
      
              return QRect(x, y, s, s);
              */
          }
          virtual bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index) override
          {
              if( !event || !view )
                  return false;
      
              if( event->type() == QEvent::ToolTip )
              {
                  QVariant tooltip = index.data( Qt::DisplayRole );
                  if( QApplication::keyboardModifiers() == Qt::AltModifier )
                  {
                      QToolTip::showText( event->globalPos(), tooltipText);
                  }
                  else
                  {
                      QToolTip::showText( event->globalPos(), tooltipText);
                  }
      
                  if( !QStyledItemDelegate::helpEvent( event, view, option, index ) )
                      QToolTip::hideText();
                  return true;
              }
      
              return QStyledItemDelegate::helpEvent( event, view, option, index );
          }
      private:
          mutable QModelIndex currentIndex;
          QPainter* mPainter;
          QString m_buttonText;
          QIcon m_buttonIcon;
          bool mIsChecked;
          bool isDetailsButton;
          bool isEnabled;
          bool isHidden;
          QString tooltipText;
          QTableWidget* tableWidget;
      
          void clickedHelper()
          {
              clicked(currentIndex);
          }
          void mouseInHelper()
          {
              mouseIn(currentIndex);
          }
      };
      #endif // BUTTONDELEGATE_H
      

      mybutton.h

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

      main.cpp

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

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

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

      H 1 Reply Last reply
      1
      • JoeCFDJ Offline
        JoeCFDJ Offline
        JoeCFD
        wrote on last edited by
        #2

        one way to do it.
        https://www.qtcentre.org/threads/3416-Center-a-widget-in-a-cell-on-a-QTableWidget
        you may try delegate as well

        H 1 Reply Last reply
        0
        • JoeCFDJ JoeCFD

          one way to do it.
          https://www.qtcentre.org/threads/3416-Center-a-widget-in-a-cell-on-a-QTableWidget
          you may try delegate as well

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

          @JoeCFD yeah that's one way to do it but it is not a very elegant solution imo.
          How would I do it with delegate?

          1 Reply Last reply
          0
          • JoeCFDJ Offline
            JoeCFDJ Offline
            JoeCFD
            wrote on last edited by
            #4

            https://forum.qt.io/topic/110557/alignment-for-qcheckbox-in-qtablewidget/13

            H 1 Reply Last reply
            0
            • JoeCFDJ JoeCFD

              https://forum.qt.io/topic/110557/alignment-for-qcheckbox-in-qtablewidget/13

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

              @JoeCFD I was able to solve by doing this:

              QPushButton* detailsButton = new QPushButton;
              detailsButton->setFixedSize(20, 15);
              
              QHBoxLayout* hLayout = new QHBoxLayout;
              hLayout->addStretch();
              hLayout->addWidget(detailsButton);
              widget->setLayout(hLayout);
              
              ui->table->setItem(row, 0, new QTableWidgetItem(ttitle));
              ui->table->setIndexWidget(ui->table->model()->index(row, 0), widget);
              

              Thanks for the help.

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

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

                "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
                • H hbatalha

                  @JoeCFD I was able to solve by doing this:

                  QPushButton* detailsButton = new QPushButton;
                  detailsButton->setFixedSize(20, 15);
                  
                  QHBoxLayout* hLayout = new QHBoxLayout;
                  hLayout->addStretch();
                  hLayout->addWidget(detailsButton);
                  widget->setLayout(hLayout);
                  
                  ui->table->setItem(row, 0, new QTableWidgetItem(ttitle));
                  ui->table->setIndexWidget(ui->table->model()->index(row, 0), widget);
                  

                  Thanks for the help.

                  JoeCFDJ Offline
                  JoeCFDJ Offline
                  JoeCFD
                  wrote on last edited by JoeCFD
                  #7

                  @hbatalha agree that it is not elegant to do it this way. But it is not bad to have your code working at first. Someday, you may be able to find a better way to do it.

                  1 Reply Last reply
                  0
                  • VRoninV VRonin

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

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

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

                    VRoninV 1 Reply Last reply
                    0
                    • H hbatalha

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

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

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

                      the buttons are only visible when the row is selected

                      Just remove:

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

                      and I can't click it.

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

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

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

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

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

                      H 1 Reply Last reply
                      2
                      • VRoninV VRonin

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

                        the buttons are only visible when the row is selected

                        Just remove:

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

                        and I can't click it.

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

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

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

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

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

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

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

                        VRoninV 1 Reply Last reply
                        0
                        • H hbatalha

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

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

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

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

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

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

                          Can you show your code?

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

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

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

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

                          H 1 Reply Last reply
                          3
                          • VRoninV VRonin

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

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

                            Can you show your code?

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

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

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

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

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

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

                            I Will try that, I am curious to see it

                            Can you show your code?

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

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

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

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

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

                              Also the button is still not clickable

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

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

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

                                Then you can use it with something like:

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

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

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

                                H 1 Reply Last reply
                                2
                                • H hbatalha

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

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

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

                                  I Will try that, I am curious to see it

                                  Can you show your code?

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

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

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

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

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

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

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

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

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

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

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

                                  1 Reply Last reply
                                  0
                                  • VRoninV VRonin

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

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

                                    Then you can use it with something like:

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

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

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

                                    but it is not working.

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

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

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

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

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

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

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

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

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

                                          H 1 Reply Last reply
                                          1
                                          • VRoninV VRonin

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

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

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

                                            VRoninV 1 Reply Last reply
                                            0

                                            • Login

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