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:
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
All these delegate integrated within QtableView control using a *m_modelo as a class of QstandardItem.
there are altogether 7 column in QtableView control
Delegate m_prodid get filled with database table field product code and ready for selection as drop-down items list.
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.
Following source code will give some understanding what trying to achieve? 
#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;
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
The following png image gives what suppose to source code should be doing?
An expected logic from above source codes
Result: