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. QItemDelegate with QComboBox and QSpinBox with QTableView control (how to pass signal)
Forum Updated to NodeBB v4.3 + New Features

QItemDelegate with QComboBox and QSpinBox with QTableView control (how to pass signal)

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

    Hi Forum,
    I wonder if someone can put me in the right direction, with his/her wisdom and skill of Qt programming as I have following logic issue with my project:

    1/ I am using three different controls of delegate with QtableView

    i ) ProdIdDelegate public QItemDelegate creates a QcomboBox delegate for m_prodid
    ii ) QtySpinDelegate public QitemDelegate create a QspinBox delegate for m_qty
    iii ) TaxCDelegate public QitemDelegate create a QcomboBox delegate for m_taxcode

    2/ All these delegate integrated within QtableView control using a *m_modelo as a class of QstandardItem.
    3/ there are altogether 7 column in QtableView control
    4/ Delegate m_prodid get filled with database table field product code and ready for selection as drop-down items list.
    4/ All three delegate has a SIGNAL/SLOT respectively their appropriate scan n search
    QcomboBox(m_prodid) : CurrentIndexChanged(QString) SLOT (myscan descript_n_price)

    The real question is:
    Upon selection of any item from the drop-down combo box its search result such as description and price can be displayed in the QtableView’s column with real-time effect ie number of time same row selection changed, the description, a price must change along with immediate effect and display must be updated at same time.

    The problem is the signal emitted by CurrentIndexChange by combo box remain within their local source file it does not cross into the main control of QtableView source file, where all formatted data displayed and calculated.

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #2
      1. do not use QItemDelegate. use QStyledItemDelegate
      2. I think all you need is connecting QComboBox::currentIndexChanged to a lambda that calls QStyledItemDelegate::commitData inside createEditor. Something like connect(comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),this,[comboBox,this](){commitData(comboBox);});

      "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

      shylockS 1 Reply Last reply
      1
      • VRoninV VRonin
        1. do not use QItemDelegate. use QStyledItemDelegate
        2. I think all you need is connecting QComboBox::currentIndexChanged to a lambda that calls QStyledItemDelegate::commitData inside createEditor. Something like connect(comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),this,[comboBox,this](){commitData(comboBox);});
        shylockS Offline
        shylockS Offline
        shylock
        wrote on last edited by
        #3

        @VRonin
        Thank you, Ronin.

        http://ftp.ics.uci.edu/pub/centos0/ics-custom-build/BUILD/PyQt-x11-gpl-4.7.2/doc/html/qstyleditemdelegate.html

        Subheading: QStyledItemDelegate vs. QItemDelegate
        What I noticed, there is the only difference between these two control is paint function which uses
        current style. My requirement as follows:

        1/ After selection from drop-down combo-box; search table for a items description and price; these two pieces of information is a string. And display in model or table-view, with concurrent synchronisation, in events selection changes.
        2/ Currently the prodId delegate work as expected mean it created an editor, data model, geometry etc along with SLOT which fire up and search the database table for a selected item. But it a requires mouse click or an interrupt to a message handler to display in the main program's TableView control. This synchronisation is failing to achieve the delegate.

        3/ I tried your advice to derive a prodIddelegate class from QStyledItemDelegate but failed to achieve an intended objective, as I poised to have in my plan.
        4/ An Idea is without mouse click or keyboard interrupt the selected data must be displayed in the TableView control and updated as selection changes. Unlike in QListbox control a slot named 'selchange' which does not require any interrupt from a mouse.

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

          Just to clarify, you want a mechanism that allows people to just hover over an option in the combobox and that, in turn, will populate the rest of the data in the module to reflect the option under the mouse?

          "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
          • shylockS Offline
            shylockS Offline
            shylock
            wrote on last edited by
            #5

            Yes. using mouse and keyboard's up n down an action. and refresh the retrieval values to their corresponding variable, without any further interruption for only for that row in the TableView main display.
            If you prefer I can attach a cut down version of a project.

            VRoninV 1 Reply Last reply
            0
            • shylockS shylock

              Yes. using mouse and keyboard's up n down an action. and refresh the retrieval values to their corresponding variable, without any further interruption for only for that row in the TableView main display.
              If you prefer I can attach a cut down version of a project.

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

              @shylock said in QItemDelegate with QComboBox and QSpinBox with QTableView control (how to pass signal):

              If you prefer I can attach a cut down version of a project.

              That would be really useful

              "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

              shylockS 2 Replies Last reply
              1
              • shylockS Offline
                shylockS Offline
                shylock
                wrote on last edited by
                #7

                [0_1508355091519_dialog.cpp](Uploading 100%)
                0_1508354940322_Invoicelayout.png
                [0_1508355042629_prodiddelegate.h](Uploading 100%) [0_1508355067261_prodiddelegate.cpp](Uploading 100%)

                1 Reply Last reply
                0
                • VRoninV VRonin

                  @shylock said in QItemDelegate with QComboBox and QSpinBox with QTableView control (how to pass signal):

                  If you prefer I can attach a cut down version of a project.

                  That would be really useful

                  shylockS Offline
                  shylockS Offline
                  shylock
                  wrote on last edited by
                  #8

                  @VRonin
                  I think the source files not got loaded!

                  #ifndef PRODIDDELEGATE_H
                  #define PRODIDDELEGATE_H
                  
                  #include "ak_connection.h"
                  #include <QItemDelegate>
                  #include <QStyledItemDelegate>
                  #include <QComboBox>
                  #include <vector>
                  #include <string>
                  
                  class ProdIdDelegate : public QStyledItemDelegate
                  {
                      Q_OBJECT
                  
                  public:
                      explicit ProdIdDelegate(QObject *parent = nullptr);
                  
                      QString getProdId () const { return m_proid;}
                      QString getDescription () const { return m_description; }
                      double getPrice () const { return m_price; }
                      void setDescription (const QString &description) {m_description = description; }
                      void setProdId(const QString &prodid) { m_proid = prodid; }
                      void setPrice (const double &price) { m_price = price; }
                  protected:
                  
                      QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                                            const QModelIndex &index) const;
                      void setEditorData(QWidget *editor, const QModelIndex &index) const;
                      void setModelData(QWidget *editor, QAbstractItemModel *model,
                                        const QModelIndex &index) const;
                      void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                                const QModelIndex &index) const;
                      void paint (QPainter *painter,
                                  const QStyleOptionViewItem &option,
                                  const QModelIndex &index) const;
                      QSize sizeHint (const QStyleOptionViewItem &option,
                                      const QModelIndex &index) const;
                  private:
                      void setValuesToVariable(QString str);
                      std::vector<std::string> Items;
                      QString m_proid;
                      QString m_description;
                      double m_price;
                      AK_connection *akdb;
                  
                  private slots:
                      void onComboItemChanged(const QString &text);
                      void commitAndCloseEditor();
                  };
                  
                  #endif // PRODIDDELEGATE_H
                  

                  Implementation file

                  #include "prodiddelegate.h"
                  #include <QComboBox>
                  #include <QDebug>
                  #include <QStyledItemDelegate>
                  #include <QSqlQuery>
                  #include <QSqlError>
                  
                  // #define _TEST_
                  
                  ProdIdDelegate::ProdIdDelegate(QObject *parent)
                      : QStyledItemDelegate (parent)
                  {   
                      (void) parent;
                  #ifdef _TEST_
                      m_description = "A Quick Borwn Fox Jump Over Little Lazy Dog.";
                      m_price = 87634.90;
                  
                      Items.push_back("Test0");
                      Items.push_back("Test1");
                      Items.push_back("Test2");
                      Items.push_back("Test3");
                      Items.push_back("Test4");
                      Items.push_back("Test5");
                      Items.push_back("Test6");
                      Items.push_back("Test7");
                      Items.push_back("Test8");
                      Items.push_back("Test9");
                  #else
                       akdb = new AK_connection(this);
                       akdb->AK_open(true);
                  #endif
                  }
                  
                  QWidget *ProdIdDelegate::createEditor(QWidget *parent,
                                                        const QStyleOptionViewItem &option,
                                                        const QModelIndex &index) const
                  {
                      QComboBox *prodId = new QComboBox(parent);
                  #ifndef _TEST_
                      QSqlQuery q;
                      q.prepare(QString("SELECT COALESCE(itemid,'') || " \
                                        "COALESCE(description,'') AS ProdId " \
                                        "FROM itemstbl WHERE status='1'"));
                  
                      if (!q.exec())
                          qDebug () << q.lastError().text();
                      while (q.next()) {
                          prodId->addItem(q.value(0).toString());
                      }
                      q.clear();
                  #else
                      for (unsigned int i=0; i < Items.size(); i++)
                          prodId->addItem(Items[i].c_str());
                  #endif
                      (void) option;
                      (void) index;
                  
                      connect(prodId, SIGNAL(currentIndexChanged(QString)), this, SLOT(onComboItemChanged(QString)));
                      return prodId;
                  }
                  void ProdIdDelegate::setEditorData(QWidget *editor,
                                                     const QModelIndex &index) const
                  {
                      QStyledItemDelegate m_siDelegate;
                  
                      if (QComboBox *cb = qobject_cast <QComboBox *> (editor)) {
                          QString curItem = index.data(Qt::EditRole).toString();
                          int cbIndex = cb->findText(curItem);
                          // Is it valid? then adjust.
                          if (cbIndex >= 0)
                              cb->setCurrentIndex(cbIndex);
                      } else {
                          m_siDelegate.setEditorData(editor, index);
                      }    
                  
                  }
                  void ProdIdDelegate::setModelData(QWidget *editor,
                                                    QAbstractItemModel *model,
                                                    const QModelIndex &index) const
                  {
                      QStyledItemDelegate m_siDelegate;
                  
                      if (QComboBox *cb = qobject_cast <QComboBox *> (editor)) {
                          // Save current text of combo box to an item.
                          model->setData(index, cb->currentText(), Qt::EditRole);
                      } else {
                          m_siDelegate.setModelData(editor, model, index);
                      }
                  }
                  void ProdIdDelegate::updateEditorGeometry(QWidget *editor,
                                                            const QStyleOptionViewItem &option,
                                                            const QModelIndex &index) const
                  {
                      editor->setGeometry(option.rect);
                      (void) index;
                  }
                  void ProdIdDelegate::paint(QPainter *painter,
                                             const QStyleOptionViewItem &option,
                                             const QModelIndex &index) const
                  {
                      (void) painter;
                      (void) option;
                      (void) index;
                  }
                  QSize ProdIdDelegate::sizeHint(const QStyleOptionViewItem &option,
                                                 const QModelIndex &index) const
                  {
                     return QStyledItemDelegate::sizeHint(option, index);
                  }
                  
                  void ProdIdDelegate::onComboItemChanged(const QString &text)
                  {    
                      emit commitData(qobject_cast <QWidget *> (sender()));
                      setProdId(text.left(5));
                      //qDebug () << "SIGNAL OnComboChanged gives string:" << text
                                //<< " File: " << __FILE__;
                      setValuesToVariable(text.left(5));
                  }
                  
                  void ProdIdDelegate::setValuesToVariable(QString str)
                  {
                  #ifdef _TEST_
                      (void) str;
                      setDescription(m_description);
                      setPrice(m_price);
                  #else
                      QSqlQuery q; q.prepare(QString("SELECT description,price FROM itemstbl "
                                                     "WHERE itemid ='%1'AND status='1'").arg(str));
                      if (!q.exec())
                          qDebug () << q.lastError().text();
                  
                      while (q.next()) {
                          setDescription(q.value(0).toString());
                          setPrice(q.value(1).toDouble());
                      }
                  #endif
                      qDebug () << "Description:" << getDescription() << "Price:" << getPrice();
                  }
                  
                  void ProdIdDelegate::commitAndCloseEditor()  // This signal yet to fired up.
                  {
                      QWidget *editor = qobject_cast <QWidget *> (sender());
                      emit commitData(editor);
                      emit closeEditor(editor);
                  }
                  

                  Main dialog.cpp

                  #include "dialog.h"
                  #include "ui_dialog.h"
                  #include "prodiddelegate.h"
                  #include "vatdelegate.h"
                  #include "qtyspin.h"
                  #include <QStandardItemModel>
                  #include <QTableWidget>
                  #include <QDebug>
                  #include <QLabel>
                  #include <cassert>
                  
                  Dialog::Dialog(QWidget *parent) :
                      QDialog(parent),
                      ui(new Ui::Dialog)
                  {
                      ui->setupUi(this);
                      QDialog::setWindowTitle(">> Invoice Delegate <<");
                      m_price = 20.87;
                      m_vatrate = 0.0;
                      m_qty     = 0;
                      /*QPixmap Invpix(":/home/imrank/gdrive/work/qtProgs/png/earth_PNG22.png");
                      QLabel hello;
                      hello.resize(128,128);
                      hello.setPixmap(Invpix);
                      QDialog::setWindowIcon(QIcon(Invpix));
                      hello.show();  */
                  
                      m_modelo         = new QStandardItemModel(this);
                      m_prodIdDelegate = new ProdIdDelegate(this);
                      m_qtyspinDelegate= new QtySpin(this);
                      m_vatDelegate    = new VATDelegate(this);
                  
                      m_modelo->setRowCount(10);
                      m_modelo->setColumnCount(7);
                  
                      m_modelo->setHorizontalHeaderItem(0, new QStandardItem("Prod ID"));
                      m_modelo->setHorizontalHeaderItem(1, new QStandardItem("Description"));
                      m_modelo->setHorizontalHeaderItem(2, new QStandardItem("Qty"));
                      m_modelo->setHorizontalHeaderItem(3, new QStandardItem("Price"));
                      m_modelo->setHorizontalHeaderItem(4, new QStandardItem("Amount"));
                      m_modelo->setHorizontalHeaderItem(5, new QStandardItem("VATAmt"));
                      m_modelo->setHorizontalHeaderItem(6, new QStandardItem("VAT"));
                  
                      ui->mytableView->setModel(m_modelo);
                      assert (ui->mytableView->model());
                  
                      // set the column width
                      ui->mytableView->setColumnWidth(0, 70);
                      ui->mytableView->setItemDelegateForColumn(0, m_prodIdDelegate);
                      ui->mytableView->showColumn(0);
                      ui->mytableView->setColumnWidth(1, 400);
                      ui->mytableView->setColumnWidth(2, 60);
                      ui->mytableView->setItemDelegateForColumn(2, m_qtyspinDelegate);
                      ui->mytableView->setColumnWidth(3, 80);
                      ui->mytableView->setColumnWidth(4, 100);
                      ui->mytableView->setColumnWidth(5, 80);
                      ui->mytableView->setColumnWidth(6, 50);
                      ui->mytableView->setItemDelegateForColumn(6, m_vatDelegate);
                  
                      QMetaObject::invokeMethod(ui->mytableView, "updateGeometries");
                  
                      for (int i=0; i<m_modelo->rowCount(); i++) {
                          ui->mytableView->openPersistentEditor(m_modelo->index(i, 0));
                          ui->mytableView->openPersistentEditor(m_modelo->index(i, 2));
                          ui->mytableView->openPersistentEditor(m_modelo->index(i, 6));
                      }
                  
                      ui->mytableView->show();
                  }
                  
                  Dialog::~Dialog()
                  {
                      delete ui;
                  }
                  
                  void Dialog::on_QuitpushButton_clicked()
                  {
                      close();
                  }
                  
                  void Dialog::on_mytableView_clicked(const QModelIndex &index)
                  {    (void) index;
                      //qDebug() << "SIGNAL: QTableView_clicked at Row " <<  index.row() << " Column " << index.column();
                      //qDebug () << "SIGNAL FROM Dialog_clicked " << ui->mytableView->model()->data(index).toString();
                      //int curCol = index.column();
                  /*
                      switch (curCol) {
                          case 0:
                              qDebug () << "ProdID " << ui->mytableView->model()->data(index).toString();
                              GetCurrentItem(index.row());
                            break;
                          case 2:
                              m_qty = ui->mytableView->model()->data(index).toInt();
                              qDebug () << "Qty" << m_qty;
                              putAmount(index.row());
                            break;
                          case 6:
                              QString code = ui->mytableView->model()->data(index).toString();
                              qDebug () << "VAT code " << code;
                              switch (code.data()->toLatin1())
                              {
                                  case 'S': m_vatrate = 20.0; break;
                                  case 'H': m_vatrate = 10.0; break;
                                  case 'Q': m_vatrate =  5.0; break;
                                  case 'E':
                                  case 'Z': m_vatrate = 0.0; break;
                                  default:  m_vatrate = 0.0;
                              }
                              putVatAmt (index.row());
                            break;
                          //default:
                         }  */
                      qDebug () << "Description" << m_prodIdDelegate->getProdId();
                      qDebug () << "Price" << m_prodIdDelegate->getPrice();
                      qDebug () << "QTY came:" << m_qtyspinDelegate->getQty();
                      qDebug () << "VAT Rate came" << m_vatDelegate->getVATRate();
                  }
                  
                  void Dialog::on_mytableView_doubleClicked(const QModelIndex &index)
                  {
                      qDebug() << "SIGNAL: QTableView_doubleClicked at Row " << index.row() << " Column " << index.column();
                  }
                  
                  void Dialog::GetCurrentItem(int rowCount)
                  {   QString myprc = QString("%1").arg(m_price);
                      QStandardItem *m_descrpt = new QStandardItem("This is a test procedure");
                      QStandardItem *m_pric   = new QStandardItem(myprc);
                      m_modelo->setItem(rowCount, 1, m_descrpt);
                      m_modelo->setItem(rowCount, 3, m_pric);
                  }
                  
                  void Dialog::putAmount(int rowCount)
                  {
                      double amt = m_price * m_qty;
                      QString stramt = QString("%1").arg(amt);
                      QStandardItem *m_amt     = new QStandardItem(stramt);
                      m_modelo->setItem(rowCount, 4, m_amt);
                  }
                  void Dialog::putVatAmt(int rowCount)
                  {
                      qDebug () << "VATrate" << m_vatrate;
                      double vatam = (((m_price * m_qty) * m_vatrate) /100);
                      QString strvat = QString("%1").arg(vatam);
                      QStandardItem  *m_vatamt = new QStandardItem(strvat);
                      m_modelo->setItem(rowCount, 5, m_vatamt);
                  }
                  
                  Header file dialog.h
                  ===============
                  #ifndef DIALOG_H
                  #define DIALOG_H
                  
                  #include <QDialog>
                  
                  namespace Ui {
                  class Dialog;
                  }
                  
                  class QStandardItemModel;
                  class ProdIdDelegate;
                  class VATDelegate;
                  class QtySpin;
                  class QTableWidget;
                  
                  class Dialog : public QDialog
                  {
                      Q_OBJECT
                  
                  public:
                      explicit Dialog(QWidget *parent = nullptr);
                      ~Dialog();
                  
                  private slots:
                      void on_QuitpushButton_clicked();
                      void on_mytableView_clicked(const QModelIndex &index);
                      void on_mytableView_doubleClicked(const QModelIndex &index);
                      void GetCurrentItem(int rowCount);
                      void putAmount(int rowCount);
                      void putVatAmt(int rowCount);
                  private:
                      Ui::Dialog *ui;
                  
                      QStandardItemModel *m_modelo;
                      ProdIdDelegate     *m_prodIdDelegate;
                      QtySpin            *m_qtyspinDelegate;
                      VATDelegate        *m_vatDelegate;
                      QTableWidget       *m_curRow;
                      QString            m_pid;
                      double             m_vatrate;
                      double             m_price;
                      int                m_qty;
                  };
                  
                  #endif // DIALOG_H
                  
                  1 Reply Last reply
                  0
                  • VRoninV VRonin

                    @shylock said in QItemDelegate with QComboBox and QSpinBox with QTableView control (how to pass signal):

                    If you prefer I can attach a cut down version of a project.

                    That would be really useful

                    shylockS Offline
                    shylockS Offline
                    shylock
                    wrote on last edited by
                    #9

                    @VRonin
                    I wonder did anyone managed to figure out, above stated problem logic?
                    Although I have a crude solution for the same problem which works. But I am interested to have more efficient and less CPU intensive solution, I am sure there were many Qt experts exists on the Forum with huge points in their credit, surely may have to jog their Qt knowledge to an extra mile or on a treadmill?

                    VRoninV 1 Reply Last reply
                    0
                    • shylockS shylock

                      @VRonin
                      I wonder did anyone managed to figure out, above stated problem logic?
                      Although I have a crude solution for the same problem which works. But I am interested to have more efficient and less CPU intensive solution, I am sure there were many Qt experts exists on the Forum with huge points in their credit, surely may have to jog their Qt knowledge to an extra mile or on a treadmill?

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

                      @shylock Sorry, I was away for a few days, I'll have a look at it today

                      "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
                      1
                      • VRoninV Offline
                        VRoninV Offline
                        VRonin
                        wrote on last edited by
                        #11

                        Unfortunately the posted code is not enough to test it.

                        A few notes/questions:

                        • What should QStyledItemDelegate m_siDelegate; do?
                        • ProdIdDelegate::paint doesn't do anything. is that what you want?
                        • ProdIdDelegate::sizeHint why do you reimplement it? just delete it
                        • ui->mytableView->openPersistentEditor why do you use this if you are using a custom delegate?
                        • Why do you call a query evey time to refresh the combo instead of just using a member QSqlTableModel?
                        • What should ProdIdDelegate::m_proid, ProdIdDelegate::m_description, ProdIdDelegate::m_price represent?

                        "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

                        shylockS 2 Replies Last reply
                        0
                        • VRoninV VRonin

                          Unfortunately the posted code is not enough to test it.

                          A few notes/questions:

                          • What should QStyledItemDelegate m_siDelegate; do?
                          • ProdIdDelegate::paint doesn't do anything. is that what you want?
                          • ProdIdDelegate::sizeHint why do you reimplement it? just delete it
                          • ui->mytableView->openPersistentEditor why do you use this if you are using a custom delegate?
                          • Why do you call a query evey time to refresh the combo instead of just using a member QSqlTableModel?
                          • What should ProdIdDelegate::m_proid, ProdIdDelegate::m_description, ProdIdDelegate::m_price represent?
                          shylockS Offline
                          shylockS Offline
                          shylock
                          wrote on last edited by
                          #12

                          @VRonin
                          1/ The vars editor,model,index simply to reuse them instead of having a warning messages.
                          2/ ProdIdDelegate::paint does not do anything due it does not have a handle of myTableView control which
                          resides in dialog class, hence it cant precisely paint the column 2 and 3
                          3/ Ignore::sizeHint function it is there and according to QStyledItemDelegate help note this function can be
                          overwritten.
                          4/ First time SQL Query called to fill or populate the QComboBox for user's selection, after selection prodId
                          The second time SQL Query called find description and price. Although This can be amalgamated in a single
                          call. But I thought since I have a Signal to process I can use this facility to re-scan the table again with
                          prodId pick the Description, and Price; this info extracted from a SQLITE3 table and displayed in
                          Dialog::myTableView table column 1 and 3 respectively. m_prodId, m_description, are string variable and
                          m_price is double.
                          5/ If you see the attached png file will explain a bit more in details.

                          1 Reply Last reply
                          0
                          • VRoninV VRonin

                            Unfortunately the posted code is not enough to test it.

                            A few notes/questions:

                            • What should QStyledItemDelegate m_siDelegate; do?
                            • ProdIdDelegate::paint doesn't do anything. is that what you want?
                            • ProdIdDelegate::sizeHint why do you reimplement it? just delete it
                            • ui->mytableView->openPersistentEditor why do you use this if you are using a custom delegate?
                            • Why do you call a query evey time to refresh the combo instead of just using a member QSqlTableModel?
                            • What should ProdIdDelegate::m_proid, ProdIdDelegate::m_description, ProdIdDelegate::m_price represent?
                            shylockS Offline
                            shylockS Offline
                            shylock
                            wrote on last edited by
                            #13

                            @VRonin
                            The posted code file Dialog.cpp; from constructor, if you remove two variables, whose code is not posted
                            m_qtyspinDelegate= new QtySpin(this);
                            m_vatDelegate = new VATDelegate(this);

                            This program a compile successfully and run with single QComboBox Delegate.

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

                              I'm missing the ui file.

                              Btw it looks like you are trying to use the delegate to do something that should not do. a delegate should paint and handle the edit of 1 and only 1 QModelIndex.

                              Remove ui->mytableView->openPersistentEditor as it just destroys performance.

                              this is a possible implementation of a combo box delegate I had around:

                              header

                              #ifndef COMBOBOXDELEGATE_H
                              #define COMBOBOXDELEGATE_H
                              
                              #include <QStyledItemDelegate>
                              #include <QString>
                              class QComboBox;
                              class QStandardItemModel;
                              class QSortFilterProxyModel;
                              class ComboBoxDelegate : public QStyledItemDelegate
                              {
                                  Q_OBJECT
                                  Q_DISABLE_COPY(ComboBoxDelegate)
                              public:
                                  ComboBoxDelegate(QObject *parent = Q_NULLPTR);
                                  virtual ~ComboBoxDelegate() = default;
                                  virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                  virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                  virtual void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                  virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                  virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                  virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index)  const Q_DECL_OVERRIDE;
                                  virtual void clear();
                                  virtual void addItem(const QString& txt, const QVariant& val);
                                  virtual void addItem(const QString& txt);
                                  virtual QString textForData(const QVariant& val);
                                  virtual void setItemData(int index, const QVariant& data, int role = Qt::UserRole);
                                  virtual QVariant itemData(int index, int role = Qt::UserRole);
                                  virtual void removeItem(int index);
                                  virtual int findText(const QString & text) const;
                                  virtual int findData(const QVariant & data, int role = Qt::UserRole) const;
                                  virtual QAbstractItemModel* model() const;
                                  bool alwaysPaintCombo() const;
                                  void setAlwaysPaintCombo(bool val);
                              protected:
                                  QStandardItemModel* m_comboModel;
                                  QSortFilterProxyModel* m_comboProxy;
                                  bool m_alwaysPaintCombo;
                              };
                              
                              #endif // COMBOBOXDELEGATE_H
                              

                              Source

                              #include "ComboBoxDelegate.h"
                              #include <QComboBox>
                              #include <QStandardItemModel>
                              #include <QApplication>
                              #include <QSortFilterProxyModel>
                              #include <QStyleOptionComboBox>
                              ComboBoxDelegate::ComboBoxDelegate(QObject *parent)
                                  : QStyledItemDelegate(parent)
                                  , m_alwaysPaintCombo(false)
                              {
                                  m_comboModel = new QStandardItemModel(this);
                                  m_comboModel->insertColumn(0);
                                  m_comboProxy = new QSortFilterProxyModel(this);
                                  m_comboProxy->setSourceModel(m_comboModel);
                              }
                              
                              void ComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
                              {
                                  if (!m_alwaysPaintCombo)
                                      return ComboBoxDelegate::paint(painter, option, index);
                                  const QWidget* const widget = option.widget;
                                  QStyle* const style = widget ? widget->style() : QApplication::style();
                                  QStyleOptionComboBox cbOption;
                                  cbOption.rect = option.rect;
                                  cbOption.direction = option.direction;
                                  cbOption.currentIcon = index.data(Qt::DecorationRole).value<QIcon>();
                                  cbOption.currentText = index.data(Qt::DisplayRole).toString();
                                  cbOption.fontMetrics = option.fontMetrics;
                                  const int iconWidth = style->pixelMetric(QStyle::PM_SmallIconSize, Q_NULLPTR, widget);
                                  cbOption.iconSize = QSize(iconWidth, iconWidth);
                                  cbOption.palette = option.palette;
                                  cbOption.state = option.state;
                                  cbOption.styleObject = option.styleObject;
                                  style->drawComplexControl(QStyle::CC_ComboBox, &cbOption, painter, widget);
                                  style->drawControl(QStyle::CE_ComboBoxLabel, &cbOption, painter, widget);
                              }
                              
                              QWidget* ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
                              {
                                  QComboBox* result = new QComboBox(parent);
                                  m_comboProxy->sort(0);
                                  result->setModel(m_comboProxy);
                                  return result;
                              }
                              
                              void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
                              {
                                  if (index.model()->data(index, Qt::EditRole).isNull())
                                      qobject_cast<QComboBox*>(editor)->setCurrentIndex(-1);
                                  else
                                      qobject_cast<QComboBox*>(editor)->setCurrentText(index.model()->data(index, Qt::EditRole).toString());
                              }
                              
                              void ComboBoxDelegate::clear()
                              {
                                  m_comboModel->removeRows(0,m_comboModel->rowCount());
                              }
                              
                              void ComboBoxDelegate::addItem(const QString& txt, const QVariant& val)
                              {
                                  const int newRow = m_comboModel->rowCount();
                                  m_comboModel->insertRow(newRow);
                                  m_comboModel->setData(m_comboModel->index(newRow, 0), txt);
                                  m_comboModel->setData(m_comboModel->index(newRow, 0), val, Qt::UserRole);
                              }
                              
                              void ComboBoxDelegate::addItem(const QString& txt)
                              {
                                  addItem(txt, QVariant());
                              }
                              
                              QString ComboBoxDelegate::textForData(const QVariant& val)
                              {
                                  for (int i = 0; i < m_comboModel->rowCount();++i){
                                      if (m_comboModel->index(i, 0).data(Qt::UserRole) == val)
                                          return m_comboModel->index(i, 0).data().toString();
                                  }
                                  return QString();
                              }
                              
                              void ComboBoxDelegate::setItemData(int index, const QVariant& data, int role)
                              {
                                  if (index < 0 || index >= m_comboProxy->rowCount())
                                      return;
                                  m_comboModel->setData(m_comboProxy->mapToSource(m_comboProxy->index(index, 0)), data, role);
                              }
                              
                              QVariant ComboBoxDelegate::itemData(int index, int role)
                              {
                                  if (index < 0 || index >= m_comboProxy->rowCount())
                                      return QVariant();
                                  return m_comboProxy->index(index, 0).data(role);
                              }
                              
                              void ComboBoxDelegate::removeItem(int index)
                              {
                                  if (index < 0 || index >= m_comboProxy->rowCount())
                                      return;
                                  m_comboModel->removeRow(m_comboProxy->mapToSource(m_comboProxy->index(index,0)).row());
                              }
                              
                              int ComboBoxDelegate::findText(const QString & text) const
                              {
                                  for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                      if (m_comboProxy->index(i, 0).data().toString().compare(text, Qt::CaseInsensitive) == 0)
                                          return i;
                                  }
                                  return -1;
                              }
                              
                              int ComboBoxDelegate::findData(const QVariant & data, int role) const
                              {
                                  for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                      if (m_comboProxy->index(i, 0).data(role) == data)
                                          return i;
                                  }
                                  return -1;
                              }
                              
                              QAbstractItemModel* ComboBoxDelegate::model() const
                              {
                                  return m_comboModel;
                              }
                              
                              bool ComboBoxDelegate::alwaysPaintCombo() const
                              {
                                  return m_alwaysPaintCombo;
                              }
                              
                              void ComboBoxDelegate::setAlwaysPaintCombo(bool val)
                              {
                                  m_alwaysPaintCombo = val;
                              }
                              
                              void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
                              {
                                  auto combo = qobject_cast<QComboBox*>(editor);
                                  if (combo->currentIndex() < 0) {
                                      model->setData(index, QVariant(), Qt::EditRole);
                                      model->setData(index, QVariant(), Qt::UserRole);
                                  }
                                  else {
                                      model->setData(index, combo->currentText(), Qt::EditRole);
                                      model->setData(index, combo->currentData(), Qt::UserRole);
                                  }
                              }
                              void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const
                              {
                                  editor->setGeometry(option.rect);
                              }
                              
                              QSize ComboBoxDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &) const
                              {
                                  int MaxWid = 0;
                                  for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                      if (option.fontMetrics.width(m_comboProxy->index(i, 0).data().toString())>MaxWid)
                                          MaxWid = option.fontMetrics.width(m_comboProxy->index(i, 0).data().toString());
                                  }
                                  return qApp->style()->sizeFromContents(
                                      QStyle::CT_ComboBox,
                                      &option,
                                      QSize(MaxWid, option.fontMetrics.height())
                                      );
                              }
                              

                              "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

                              shylockS C 3 Replies Last reply
                              1
                              • VRoninV VRonin

                                I'm missing the ui file.

                                Btw it looks like you are trying to use the delegate to do something that should not do. a delegate should paint and handle the edit of 1 and only 1 QModelIndex.

                                Remove ui->mytableView->openPersistentEditor as it just destroys performance.

                                this is a possible implementation of a combo box delegate I had around:

                                header

                                #ifndef COMBOBOXDELEGATE_H
                                #define COMBOBOXDELEGATE_H
                                
                                #include <QStyledItemDelegate>
                                #include <QString>
                                class QComboBox;
                                class QStandardItemModel;
                                class QSortFilterProxyModel;
                                class ComboBoxDelegate : public QStyledItemDelegate
                                {
                                    Q_OBJECT
                                    Q_DISABLE_COPY(ComboBoxDelegate)
                                public:
                                    ComboBoxDelegate(QObject *parent = Q_NULLPTR);
                                    virtual ~ComboBoxDelegate() = default;
                                    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                    virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                    virtual void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                    virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                    virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                    virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index)  const Q_DECL_OVERRIDE;
                                    virtual void clear();
                                    virtual void addItem(const QString& txt, const QVariant& val);
                                    virtual void addItem(const QString& txt);
                                    virtual QString textForData(const QVariant& val);
                                    virtual void setItemData(int index, const QVariant& data, int role = Qt::UserRole);
                                    virtual QVariant itemData(int index, int role = Qt::UserRole);
                                    virtual void removeItem(int index);
                                    virtual int findText(const QString & text) const;
                                    virtual int findData(const QVariant & data, int role = Qt::UserRole) const;
                                    virtual QAbstractItemModel* model() const;
                                    bool alwaysPaintCombo() const;
                                    void setAlwaysPaintCombo(bool val);
                                protected:
                                    QStandardItemModel* m_comboModel;
                                    QSortFilterProxyModel* m_comboProxy;
                                    bool m_alwaysPaintCombo;
                                };
                                
                                #endif // COMBOBOXDELEGATE_H
                                

                                Source

                                #include "ComboBoxDelegate.h"
                                #include <QComboBox>
                                #include <QStandardItemModel>
                                #include <QApplication>
                                #include <QSortFilterProxyModel>
                                #include <QStyleOptionComboBox>
                                ComboBoxDelegate::ComboBoxDelegate(QObject *parent)
                                    : QStyledItemDelegate(parent)
                                    , m_alwaysPaintCombo(false)
                                {
                                    m_comboModel = new QStandardItemModel(this);
                                    m_comboModel->insertColumn(0);
                                    m_comboProxy = new QSortFilterProxyModel(this);
                                    m_comboProxy->setSourceModel(m_comboModel);
                                }
                                
                                void ComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
                                {
                                    if (!m_alwaysPaintCombo)
                                        return ComboBoxDelegate::paint(painter, option, index);
                                    const QWidget* const widget = option.widget;
                                    QStyle* const style = widget ? widget->style() : QApplication::style();
                                    QStyleOptionComboBox cbOption;
                                    cbOption.rect = option.rect;
                                    cbOption.direction = option.direction;
                                    cbOption.currentIcon = index.data(Qt::DecorationRole).value<QIcon>();
                                    cbOption.currentText = index.data(Qt::DisplayRole).toString();
                                    cbOption.fontMetrics = option.fontMetrics;
                                    const int iconWidth = style->pixelMetric(QStyle::PM_SmallIconSize, Q_NULLPTR, widget);
                                    cbOption.iconSize = QSize(iconWidth, iconWidth);
                                    cbOption.palette = option.palette;
                                    cbOption.state = option.state;
                                    cbOption.styleObject = option.styleObject;
                                    style->drawComplexControl(QStyle::CC_ComboBox, &cbOption, painter, widget);
                                    style->drawControl(QStyle::CE_ComboBoxLabel, &cbOption, painter, widget);
                                }
                                
                                QWidget* ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
                                {
                                    QComboBox* result = new QComboBox(parent);
                                    m_comboProxy->sort(0);
                                    result->setModel(m_comboProxy);
                                    return result;
                                }
                                
                                void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
                                {
                                    if (index.model()->data(index, Qt::EditRole).isNull())
                                        qobject_cast<QComboBox*>(editor)->setCurrentIndex(-1);
                                    else
                                        qobject_cast<QComboBox*>(editor)->setCurrentText(index.model()->data(index, Qt::EditRole).toString());
                                }
                                
                                void ComboBoxDelegate::clear()
                                {
                                    m_comboModel->removeRows(0,m_comboModel->rowCount());
                                }
                                
                                void ComboBoxDelegate::addItem(const QString& txt, const QVariant& val)
                                {
                                    const int newRow = m_comboModel->rowCount();
                                    m_comboModel->insertRow(newRow);
                                    m_comboModel->setData(m_comboModel->index(newRow, 0), txt);
                                    m_comboModel->setData(m_comboModel->index(newRow, 0), val, Qt::UserRole);
                                }
                                
                                void ComboBoxDelegate::addItem(const QString& txt)
                                {
                                    addItem(txt, QVariant());
                                }
                                
                                QString ComboBoxDelegate::textForData(const QVariant& val)
                                {
                                    for (int i = 0; i < m_comboModel->rowCount();++i){
                                        if (m_comboModel->index(i, 0).data(Qt::UserRole) == val)
                                            return m_comboModel->index(i, 0).data().toString();
                                    }
                                    return QString();
                                }
                                
                                void ComboBoxDelegate::setItemData(int index, const QVariant& data, int role)
                                {
                                    if (index < 0 || index >= m_comboProxy->rowCount())
                                        return;
                                    m_comboModel->setData(m_comboProxy->mapToSource(m_comboProxy->index(index, 0)), data, role);
                                }
                                
                                QVariant ComboBoxDelegate::itemData(int index, int role)
                                {
                                    if (index < 0 || index >= m_comboProxy->rowCount())
                                        return QVariant();
                                    return m_comboProxy->index(index, 0).data(role);
                                }
                                
                                void ComboBoxDelegate::removeItem(int index)
                                {
                                    if (index < 0 || index >= m_comboProxy->rowCount())
                                        return;
                                    m_comboModel->removeRow(m_comboProxy->mapToSource(m_comboProxy->index(index,0)).row());
                                }
                                
                                int ComboBoxDelegate::findText(const QString & text) const
                                {
                                    for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                        if (m_comboProxy->index(i, 0).data().toString().compare(text, Qt::CaseInsensitive) == 0)
                                            return i;
                                    }
                                    return -1;
                                }
                                
                                int ComboBoxDelegate::findData(const QVariant & data, int role) const
                                {
                                    for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                        if (m_comboProxy->index(i, 0).data(role) == data)
                                            return i;
                                    }
                                    return -1;
                                }
                                
                                QAbstractItemModel* ComboBoxDelegate::model() const
                                {
                                    return m_comboModel;
                                }
                                
                                bool ComboBoxDelegate::alwaysPaintCombo() const
                                {
                                    return m_alwaysPaintCombo;
                                }
                                
                                void ComboBoxDelegate::setAlwaysPaintCombo(bool val)
                                {
                                    m_alwaysPaintCombo = val;
                                }
                                
                                void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
                                {
                                    auto combo = qobject_cast<QComboBox*>(editor);
                                    if (combo->currentIndex() < 0) {
                                        model->setData(index, QVariant(), Qt::EditRole);
                                        model->setData(index, QVariant(), Qt::UserRole);
                                    }
                                    else {
                                        model->setData(index, combo->currentText(), Qt::EditRole);
                                        model->setData(index, combo->currentData(), Qt::UserRole);
                                    }
                                }
                                void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const
                                {
                                    editor->setGeometry(option.rect);
                                }
                                
                                QSize ComboBoxDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &) const
                                {
                                    int MaxWid = 0;
                                    for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                        if (option.fontMetrics.width(m_comboProxy->index(i, 0).data().toString())>MaxWid)
                                            MaxWid = option.fontMetrics.width(m_comboProxy->index(i, 0).data().toString());
                                    }
                                    return qApp->style()->sizeFromContents(
                                        QStyle::CT_ComboBox,
                                        &option,
                                        QSize(MaxWid, option.fontMetrics.height())
                                        );
                                }
                                
                                shylockS Offline
                                shylockS Offline
                                shylock
                                wrote on last edited by
                                #15

                                @VRonin
                                Thank you, Ronin,
                                Although I am going through the codes, I have attached my bog standard cut down version of the program, it is not an efficient way to complete and I am still looking a more tangible solution to complete the project.
                                Your provided class seems to more help a QComboBox and its various virtual functions.
                                AS you mentioned in the last post I am trying to do away different nature of job from QStyledItemDelegate class; perhaps you are right and in my judgment, if QStyledItemDelegate class provide a facility such as combo box, spin box, progress bar sliders, and other controls can be embedded into QTableView, QListView, QTreeView then their functionality can be must be more transparent to an extend functionality suited to a developer. As in this case nothing new as you can depict from the png image.
                                I am still grappling with real-time synchronization with two combo box and qty spin box selection, with their changes while displaying info on the QTableView Grid in a formatted manner.

                                0_1508864321649_Invoicelayout_01.png

                                1 Reply Last reply
                                0
                                • VRoninV VRonin

                                  I'm missing the ui file.

                                  Btw it looks like you are trying to use the delegate to do something that should not do. a delegate should paint and handle the edit of 1 and only 1 QModelIndex.

                                  Remove ui->mytableView->openPersistentEditor as it just destroys performance.

                                  this is a possible implementation of a combo box delegate I had around:

                                  header

                                  #ifndef COMBOBOXDELEGATE_H
                                  #define COMBOBOXDELEGATE_H
                                  
                                  #include <QStyledItemDelegate>
                                  #include <QString>
                                  class QComboBox;
                                  class QStandardItemModel;
                                  class QSortFilterProxyModel;
                                  class ComboBoxDelegate : public QStyledItemDelegate
                                  {
                                      Q_OBJECT
                                      Q_DISABLE_COPY(ComboBoxDelegate)
                                  public:
                                      ComboBoxDelegate(QObject *parent = Q_NULLPTR);
                                      virtual ~ComboBoxDelegate() = default;
                                      virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                      virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                      virtual void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                      virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                      virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                      virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index)  const Q_DECL_OVERRIDE;
                                      virtual void clear();
                                      virtual void addItem(const QString& txt, const QVariant& val);
                                      virtual void addItem(const QString& txt);
                                      virtual QString textForData(const QVariant& val);
                                      virtual void setItemData(int index, const QVariant& data, int role = Qt::UserRole);
                                      virtual QVariant itemData(int index, int role = Qt::UserRole);
                                      virtual void removeItem(int index);
                                      virtual int findText(const QString & text) const;
                                      virtual int findData(const QVariant & data, int role = Qt::UserRole) const;
                                      virtual QAbstractItemModel* model() const;
                                      bool alwaysPaintCombo() const;
                                      void setAlwaysPaintCombo(bool val);
                                  protected:
                                      QStandardItemModel* m_comboModel;
                                      QSortFilterProxyModel* m_comboProxy;
                                      bool m_alwaysPaintCombo;
                                  };
                                  
                                  #endif // COMBOBOXDELEGATE_H
                                  

                                  Source

                                  #include "ComboBoxDelegate.h"
                                  #include <QComboBox>
                                  #include <QStandardItemModel>
                                  #include <QApplication>
                                  #include <QSortFilterProxyModel>
                                  #include <QStyleOptionComboBox>
                                  ComboBoxDelegate::ComboBoxDelegate(QObject *parent)
                                      : QStyledItemDelegate(parent)
                                      , m_alwaysPaintCombo(false)
                                  {
                                      m_comboModel = new QStandardItemModel(this);
                                      m_comboModel->insertColumn(0);
                                      m_comboProxy = new QSortFilterProxyModel(this);
                                      m_comboProxy->setSourceModel(m_comboModel);
                                  }
                                  
                                  void ComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
                                  {
                                      if (!m_alwaysPaintCombo)
                                          return ComboBoxDelegate::paint(painter, option, index);
                                      const QWidget* const widget = option.widget;
                                      QStyle* const style = widget ? widget->style() : QApplication::style();
                                      QStyleOptionComboBox cbOption;
                                      cbOption.rect = option.rect;
                                      cbOption.direction = option.direction;
                                      cbOption.currentIcon = index.data(Qt::DecorationRole).value<QIcon>();
                                      cbOption.currentText = index.data(Qt::DisplayRole).toString();
                                      cbOption.fontMetrics = option.fontMetrics;
                                      const int iconWidth = style->pixelMetric(QStyle::PM_SmallIconSize, Q_NULLPTR, widget);
                                      cbOption.iconSize = QSize(iconWidth, iconWidth);
                                      cbOption.palette = option.palette;
                                      cbOption.state = option.state;
                                      cbOption.styleObject = option.styleObject;
                                      style->drawComplexControl(QStyle::CC_ComboBox, &cbOption, painter, widget);
                                      style->drawControl(QStyle::CE_ComboBoxLabel, &cbOption, painter, widget);
                                  }
                                  
                                  QWidget* ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
                                  {
                                      QComboBox* result = new QComboBox(parent);
                                      m_comboProxy->sort(0);
                                      result->setModel(m_comboProxy);
                                      return result;
                                  }
                                  
                                  void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
                                  {
                                      if (index.model()->data(index, Qt::EditRole).isNull())
                                          qobject_cast<QComboBox*>(editor)->setCurrentIndex(-1);
                                      else
                                          qobject_cast<QComboBox*>(editor)->setCurrentText(index.model()->data(index, Qt::EditRole).toString());
                                  }
                                  
                                  void ComboBoxDelegate::clear()
                                  {
                                      m_comboModel->removeRows(0,m_comboModel->rowCount());
                                  }
                                  
                                  void ComboBoxDelegate::addItem(const QString& txt, const QVariant& val)
                                  {
                                      const int newRow = m_comboModel->rowCount();
                                      m_comboModel->insertRow(newRow);
                                      m_comboModel->setData(m_comboModel->index(newRow, 0), txt);
                                      m_comboModel->setData(m_comboModel->index(newRow, 0), val, Qt::UserRole);
                                  }
                                  
                                  void ComboBoxDelegate::addItem(const QString& txt)
                                  {
                                      addItem(txt, QVariant());
                                  }
                                  
                                  QString ComboBoxDelegate::textForData(const QVariant& val)
                                  {
                                      for (int i = 0; i < m_comboModel->rowCount();++i){
                                          if (m_comboModel->index(i, 0).data(Qt::UserRole) == val)
                                              return m_comboModel->index(i, 0).data().toString();
                                      }
                                      return QString();
                                  }
                                  
                                  void ComboBoxDelegate::setItemData(int index, const QVariant& data, int role)
                                  {
                                      if (index < 0 || index >= m_comboProxy->rowCount())
                                          return;
                                      m_comboModel->setData(m_comboProxy->mapToSource(m_comboProxy->index(index, 0)), data, role);
                                  }
                                  
                                  QVariant ComboBoxDelegate::itemData(int index, int role)
                                  {
                                      if (index < 0 || index >= m_comboProxy->rowCount())
                                          return QVariant();
                                      return m_comboProxy->index(index, 0).data(role);
                                  }
                                  
                                  void ComboBoxDelegate::removeItem(int index)
                                  {
                                      if (index < 0 || index >= m_comboProxy->rowCount())
                                          return;
                                      m_comboModel->removeRow(m_comboProxy->mapToSource(m_comboProxy->index(index,0)).row());
                                  }
                                  
                                  int ComboBoxDelegate::findText(const QString & text) const
                                  {
                                      for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                          if (m_comboProxy->index(i, 0).data().toString().compare(text, Qt::CaseInsensitive) == 0)
                                              return i;
                                      }
                                      return -1;
                                  }
                                  
                                  int ComboBoxDelegate::findData(const QVariant & data, int role) const
                                  {
                                      for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                          if (m_comboProxy->index(i, 0).data(role) == data)
                                              return i;
                                      }
                                      return -1;
                                  }
                                  
                                  QAbstractItemModel* ComboBoxDelegate::model() const
                                  {
                                      return m_comboModel;
                                  }
                                  
                                  bool ComboBoxDelegate::alwaysPaintCombo() const
                                  {
                                      return m_alwaysPaintCombo;
                                  }
                                  
                                  void ComboBoxDelegate::setAlwaysPaintCombo(bool val)
                                  {
                                      m_alwaysPaintCombo = val;
                                  }
                                  
                                  void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
                                  {
                                      auto combo = qobject_cast<QComboBox*>(editor);
                                      if (combo->currentIndex() < 0) {
                                          model->setData(index, QVariant(), Qt::EditRole);
                                          model->setData(index, QVariant(), Qt::UserRole);
                                      }
                                      else {
                                          model->setData(index, combo->currentText(), Qt::EditRole);
                                          model->setData(index, combo->currentData(), Qt::UserRole);
                                      }
                                  }
                                  void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const
                                  {
                                      editor->setGeometry(option.rect);
                                  }
                                  
                                  QSize ComboBoxDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &) const
                                  {
                                      int MaxWid = 0;
                                      for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                          if (option.fontMetrics.width(m_comboProxy->index(i, 0).data().toString())>MaxWid)
                                              MaxWid = option.fontMetrics.width(m_comboProxy->index(i, 0).data().toString());
                                      }
                                      return qApp->style()->sizeFromContents(
                                          QStyle::CT_ComboBox,
                                          &option,
                                          QSize(MaxWid, option.fontMetrics.height())
                                          );
                                  }
                                  
                                  shylockS Offline
                                  shylockS Offline
                                  shylock
                                  wrote on last edited by
                                  #16

                                  @VRonin
                                  I am afraid your provided class logic simply does not work as it cannot be instantiated, the function
                                  paint is persistent in the paint state for QVariants; even the list become exhausted, it gave me far more aggro to embed within QTableView.
                                  A basically I am still at Square One! The requirements (ie problem) remained stirring at me more vehemently than ever, I bet I have to go deep undercover in Qt's systems source code to do a bit of hacking.

                                  1 Reply Last reply
                                  0
                                  • MucipM Offline
                                    MucipM Offline
                                    Mucip
                                    wrote on last edited by
                                    #17

                                    Dear shlock,
                                    I need this kind of invoice detail imput tableview. May I ask please? Which kind of Database did you use and how did you add new lines and write them in DB?
                                    Regards,
                                    Mucip:)

                                    1 Reply Last reply
                                    0
                                    • VRoninV VRonin

                                      I'm missing the ui file.

                                      Btw it looks like you are trying to use the delegate to do something that should not do. a delegate should paint and handle the edit of 1 and only 1 QModelIndex.

                                      Remove ui->mytableView->openPersistentEditor as it just destroys performance.

                                      this is a possible implementation of a combo box delegate I had around:

                                      header

                                      #ifndef COMBOBOXDELEGATE_H
                                      #define COMBOBOXDELEGATE_H
                                      
                                      #include <QStyledItemDelegate>
                                      #include <QString>
                                      class QComboBox;
                                      class QStandardItemModel;
                                      class QSortFilterProxyModel;
                                      class ComboBoxDelegate : public QStyledItemDelegate
                                      {
                                          Q_OBJECT
                                          Q_DISABLE_COPY(ComboBoxDelegate)
                                      public:
                                          ComboBoxDelegate(QObject *parent = Q_NULLPTR);
                                          virtual ~ComboBoxDelegate() = default;
                                          virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                          virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                          virtual void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                          virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                          virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
                                          virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index)  const Q_DECL_OVERRIDE;
                                          virtual void clear();
                                          virtual void addItem(const QString& txt, const QVariant& val);
                                          virtual void addItem(const QString& txt);
                                          virtual QString textForData(const QVariant& val);
                                          virtual void setItemData(int index, const QVariant& data, int role = Qt::UserRole);
                                          virtual QVariant itemData(int index, int role = Qt::UserRole);
                                          virtual void removeItem(int index);
                                          virtual int findText(const QString & text) const;
                                          virtual int findData(const QVariant & data, int role = Qt::UserRole) const;
                                          virtual QAbstractItemModel* model() const;
                                          bool alwaysPaintCombo() const;
                                          void setAlwaysPaintCombo(bool val);
                                      protected:
                                          QStandardItemModel* m_comboModel;
                                          QSortFilterProxyModel* m_comboProxy;
                                          bool m_alwaysPaintCombo;
                                      };
                                      
                                      #endif // COMBOBOXDELEGATE_H
                                      

                                      Source

                                      #include "ComboBoxDelegate.h"
                                      #include <QComboBox>
                                      #include <QStandardItemModel>
                                      #include <QApplication>
                                      #include <QSortFilterProxyModel>
                                      #include <QStyleOptionComboBox>
                                      ComboBoxDelegate::ComboBoxDelegate(QObject *parent)
                                          : QStyledItemDelegate(parent)
                                          , m_alwaysPaintCombo(false)
                                      {
                                          m_comboModel = new QStandardItemModel(this);
                                          m_comboModel->insertColumn(0);
                                          m_comboProxy = new QSortFilterProxyModel(this);
                                          m_comboProxy->setSourceModel(m_comboModel);
                                      }
                                      
                                      void ComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
                                      {
                                          if (!m_alwaysPaintCombo)
                                              return ComboBoxDelegate::paint(painter, option, index);
                                          const QWidget* const widget = option.widget;
                                          QStyle* const style = widget ? widget->style() : QApplication::style();
                                          QStyleOptionComboBox cbOption;
                                          cbOption.rect = option.rect;
                                          cbOption.direction = option.direction;
                                          cbOption.currentIcon = index.data(Qt::DecorationRole).value<QIcon>();
                                          cbOption.currentText = index.data(Qt::DisplayRole).toString();
                                          cbOption.fontMetrics = option.fontMetrics;
                                          const int iconWidth = style->pixelMetric(QStyle::PM_SmallIconSize, Q_NULLPTR, widget);
                                          cbOption.iconSize = QSize(iconWidth, iconWidth);
                                          cbOption.palette = option.palette;
                                          cbOption.state = option.state;
                                          cbOption.styleObject = option.styleObject;
                                          style->drawComplexControl(QStyle::CC_ComboBox, &cbOption, painter, widget);
                                          style->drawControl(QStyle::CE_ComboBoxLabel, &cbOption, painter, widget);
                                      }
                                      
                                      QWidget* ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
                                      {
                                          QComboBox* result = new QComboBox(parent);
                                          m_comboProxy->sort(0);
                                          result->setModel(m_comboProxy);
                                          return result;
                                      }
                                      
                                      void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
                                      {
                                          if (index.model()->data(index, Qt::EditRole).isNull())
                                              qobject_cast<QComboBox*>(editor)->setCurrentIndex(-1);
                                          else
                                              qobject_cast<QComboBox*>(editor)->setCurrentText(index.model()->data(index, Qt::EditRole).toString());
                                      }
                                      
                                      void ComboBoxDelegate::clear()
                                      {
                                          m_comboModel->removeRows(0,m_comboModel->rowCount());
                                      }
                                      
                                      void ComboBoxDelegate::addItem(const QString& txt, const QVariant& val)
                                      {
                                          const int newRow = m_comboModel->rowCount();
                                          m_comboModel->insertRow(newRow);
                                          m_comboModel->setData(m_comboModel->index(newRow, 0), txt);
                                          m_comboModel->setData(m_comboModel->index(newRow, 0), val, Qt::UserRole);
                                      }
                                      
                                      void ComboBoxDelegate::addItem(const QString& txt)
                                      {
                                          addItem(txt, QVariant());
                                      }
                                      
                                      QString ComboBoxDelegate::textForData(const QVariant& val)
                                      {
                                          for (int i = 0; i < m_comboModel->rowCount();++i){
                                              if (m_comboModel->index(i, 0).data(Qt::UserRole) == val)
                                                  return m_comboModel->index(i, 0).data().toString();
                                          }
                                          return QString();
                                      }
                                      
                                      void ComboBoxDelegate::setItemData(int index, const QVariant& data, int role)
                                      {
                                          if (index < 0 || index >= m_comboProxy->rowCount())
                                              return;
                                          m_comboModel->setData(m_comboProxy->mapToSource(m_comboProxy->index(index, 0)), data, role);
                                      }
                                      
                                      QVariant ComboBoxDelegate::itemData(int index, int role)
                                      {
                                          if (index < 0 || index >= m_comboProxy->rowCount())
                                              return QVariant();
                                          return m_comboProxy->index(index, 0).data(role);
                                      }
                                      
                                      void ComboBoxDelegate::removeItem(int index)
                                      {
                                          if (index < 0 || index >= m_comboProxy->rowCount())
                                              return;
                                          m_comboModel->removeRow(m_comboProxy->mapToSource(m_comboProxy->index(index,0)).row());
                                      }
                                      
                                      int ComboBoxDelegate::findText(const QString & text) const
                                      {
                                          for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                              if (m_comboProxy->index(i, 0).data().toString().compare(text, Qt::CaseInsensitive) == 0)
                                                  return i;
                                          }
                                          return -1;
                                      }
                                      
                                      int ComboBoxDelegate::findData(const QVariant & data, int role) const
                                      {
                                          for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                              if (m_comboProxy->index(i, 0).data(role) == data)
                                                  return i;
                                          }
                                          return -1;
                                      }
                                      
                                      QAbstractItemModel* ComboBoxDelegate::model() const
                                      {
                                          return m_comboModel;
                                      }
                                      
                                      bool ComboBoxDelegate::alwaysPaintCombo() const
                                      {
                                          return m_alwaysPaintCombo;
                                      }
                                      
                                      void ComboBoxDelegate::setAlwaysPaintCombo(bool val)
                                      {
                                          m_alwaysPaintCombo = val;
                                      }
                                      
                                      void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
                                      {
                                          auto combo = qobject_cast<QComboBox*>(editor);
                                          if (combo->currentIndex() < 0) {
                                              model->setData(index, QVariant(), Qt::EditRole);
                                              model->setData(index, QVariant(), Qt::UserRole);
                                          }
                                          else {
                                              model->setData(index, combo->currentText(), Qt::EditRole);
                                              model->setData(index, combo->currentData(), Qt::UserRole);
                                          }
                                      }
                                      void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const
                                      {
                                          editor->setGeometry(option.rect);
                                      }
                                      
                                      QSize ComboBoxDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &) const
                                      {
                                          int MaxWid = 0;
                                          for (int i = 0; i < m_comboProxy->rowCount(); ++i) {
                                              if (option.fontMetrics.width(m_comboProxy->index(i, 0).data().toString())>MaxWid)
                                                  MaxWid = option.fontMetrics.width(m_comboProxy->index(i, 0).data().toString());
                                          }
                                          return qApp->style()->sizeFromContents(
                                              QStyle::CT_ComboBox,
                                              &option,
                                              QSize(MaxWid, option.fontMetrics.height())
                                              );
                                      }
                                      
                                      C Offline
                                      C Offline
                                      charry
                                      wrote on last edited by
                                      #18

                                      @VRonin hi, I run the code sucess, how to keep baseEditor always display not that I should click the mouse.

                                      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