PDA

View Full Version : updating database with custom delegate



Shaitan
17th July 2007, 10:05
Hi!
I have a QTableWidget linked to a custom delegate, which has a QDateEdit column (0) and 2 QComboBox columns (1 and 3). I also have a QSqlTableModel which is conected to a table inside an MS access DB (used for simplicity). I can load the data for the QTableWidget correctly from the Db, but when i change any field in the QTableWidget and make the changes to the model, the DB doesnt update (i call submitAll()). I think that the problem must be soemthing about the QSqlModel and the model of the QTableWidget (i cant call QTableWidget::setModel(), as it is a private func. - at least that says the compiler).

This is my code:



#include "comprasDelegate.h"


sqlQtPro::sqlQtPro(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);

this->loadAccessDatabase("base2.mdb");
this->loadModels();

dialogoProveedores=new dialogProvedores(this, modelProveedores);

ui.botTerminarCompra->setVisible(false);

//prueba combo
ui.viewCompras->setHorizontalHeaderLabels(QStringList() << tr("Fecha")
<< tr("Proveedor") << tr("Importe")
<< tr("IVA") << tr("Total"));
this->rellenarListaCompras();

QObject::connect(ui.actionProveedores, SIGNAL(triggered()),
this, SLOT(showProveedores(void)));
QObject::connect(ui.botAddCompra, SIGNAL(clicked()),this, SLOT(addCompras(void)));
QObject::connect(this->mComprasDelegate,SIGNAL(commitData(QWidget*)),this ,SLOT(updateComprasTable()));

}

int sqlQtPro::loadAccessDatabase(QString fileName)
{
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setDatabaseName("DRIVER={Microsoft Access Driver (*.mdb)};FIL={MS Access};DBQ="+fileName.toLatin1());
if (!db.open()) {
QMessageBox::critical(0, qApp->tr("Cannot open database"),
qApp->tr("Imposible establecer conexión con la Base de Datos ODBC.\n\n"

"Presiona Cancelar para salir."), QMessageBox::Cancel);
return false;
}else
{
return true;
}
}

void sqlQtPro::loadModels()
{
modelCompras=new QSqlTableModel(this);
modelCompras->setTable("Compras");
modelCompras->setEditStrategy(QSqlTableModel::OnManualSubmit);
modelCompras->select();
modelCompras->setHeaderData(0, Qt::Horizontal, QObject::tr("Fecha"));
modelCompras->setHeaderData(1, Qt::Horizontal, QObject::tr("Proveedor"));
modelCompras->setHeaderData(2, Qt::Horizontal, QObject::tr("Importe"));
modelCompras->setHeaderData(3, Qt::Horizontal, QObject::tr("IVA"));
modelCompras->setHeaderData(4, Qt::Horizontal, QObject::tr("Importe final"));


//ui.viewCompras->setModel(modelCompras);


}




void sqlQtPro::rellenarListaCompras()
{

mComprasDelegate = new ComprasDelegate(this);
ui.viewCompras->setItemDelegate(mComprasDelegate);
for (int i=0; i<modelProveedores->rowCount(); ++i)
mComprasDelegate->insertProveedor(modelProveedores->index(i,0).data().toString());

for (int i=0; i<modelCompras->rowCount();++i)
{
int row=ui.viewCompras->rowCount();
ui.viewCompras->setRowCount(row+1);
QTableWidgetItem *item0 = new QTableWidgetItem(modelCompras->index(i,0).data().toString());
QTableWidgetItem *item1 = new QTableWidgetItem(modelCompras->index(i,1).data().toString());
QTableWidgetItem *item2 = new QTableWidgetItem(modelCompras->index(i,2).data().toString());
QTableWidgetItem *item3 = new QTableWidgetItem(modelCompras->index(i,3).data().toString());
QTableWidgetItem *item4 = new QTableWidgetItem(modelCompras->index(i,4).data().toString());
ui.viewCompras->setItem(i, 0, item0);
ui.viewCompras->setItem(i, 1, item1);
ui.viewCompras->setItem(i, 2, item2);
ui.viewCompras->setItem(i, 3, item3);
ui.viewCompras->setItem(i, 4, item4);
ui.viewCompras->openPersistentEditor(item0);
ui.viewCompras->openPersistentEditor(item1);
ui.viewCompras->openPersistentEditor(item3);

}
ui.viewCompras->resizeColumnsToContents();
ui.viewCompras->sortByColumn(0);
}

void sqlQtPro::updateComprasTable()
{
if(!modelCompras->submitAll())
QMessageBox::warning(this, tr("Cached Table"),
tr("The database reported an error: %1").arg(modelCompras->lastError().text()));
//else modelCompras->database().commit();
}


comprasDelegate.cpp

#include "ComprasDelegate.h"

QStringList ComprasDelegate::sListaProveedores;

ComprasDelegate::ComprasDelegate(QObject *parent)
: QItemDelegate(parent)
{
}

QWidget *ComprasDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem & /* option */,
const QModelIndex &index) const
{
QWidget* retWidget=NULL;;
if((index.column()==1)||(index.column()==3))
{
QComboBox *comboBox = new QComboBox(parent);
if (index.column() == 1) {
comboBox->addItems(sListaProveedores);
} else if (index.column() == 3) {
comboBox->addItem(tr("7%"));
comboBox->addItem(tr("16%"));
}
connect(comboBox, SIGNAL(activated(int)), this, SLOT(emitCommitData()));
retWidget=comboBox;
}else if (index.column()==0)
{
QDateEdit *edit= new QDateEdit(parent);
edit->setDisplayFormat("dd/MM/yyyy");
connect(edit, SIGNAL(dateChanged(QDate)), this, SLOT(emitCommitData()));
retWidget=edit;
}
return retWidget;
}

void ComprasDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
if (index.column()==0)
{
QDateEdit * edit=qobject_cast<QDateEdit*>(editor);
if(!edit) return;

edit->blockSignals(true);
edit->setDate(QDate::fromString(index.model()->data(index).toString(),"yyyy-MM-ddT00:00:00"));
edit->blockSignals(false);
}
else if (index.column()==1)
{
QComboBox *comboBox = qobject_cast<QComboBox *>(editor);
if (!comboBox)
return;

int pos = comboBox->findText(index.model()->data(index).toString(),Qt::MatchExactly);
comboBox->setCurrentIndex(pos);
}


}

void ComprasDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
if (index.column()==0)
{
QDateEdit * edit=qobject_cast<QDateEdit*>(editor);
if(!edit) return;

model->setData(index,"pp");
QMessageBox::critical(0, qApp->tr("set data"),
qApp->tr("set data '"+edit->date().toString("dd/MM/yyyy").toLatin1()+"'\n\n"
"Presiona Cancelar para salir."), QMessageBox::Cancel);
if(!model->setData(index,edit->date().toString("dd/MM/yyyy")))
QMessageBox::critical(0, qApp->tr("Fecha"),
qApp->tr("'error introd. fecha'\n\n"
"Presiona Cancelar para salir."), QMessageBox::Cancel);

//edit->setDate(QDate::fromString(index.model()->data(index).toString(),"dd/MM/yyyy"));
}
else if (index.column()==1)
{
QComboBox *comboBox = qobject_cast<QComboBox *>(editor);
if (!comboBox)
return;

if(!model->setData(index, comboBox->currentText()))
QMessageBox::critical(0, qApp->tr("Fecha"),
qApp->tr("'error introd. data combo'\n\n"
"Presiona Cancelar para salir."), QMessageBox::Cancel);
}

}

void ComprasDelegate::emitCommitData()
{
emit commitData(qobject_cast<QWidget *>(sender()));
/*QMessageBox::critical(0, qApp->tr("Fecha"),
qApp->tr("'commit data'\n\n"
"Presiona Cancelar para salir."), QMessageBox::Cancel);*/
}

void ComprasDelegate::insertProveedor(QString proveedor)
{
sListaProveedores.push_back(proveedor);
}

Any idea??

Thx!!

J.

jpn
17th July 2007, 10:08
Use QTableView to show contents of a model. QTableWidget has a built-in model which is not supposed to be changed.

From QTableWidget docs:


The QTableWidget class provides an item-based table view with a default model.

...

If you want a table that uses your own data model you should use QTableView rather than this class.

Shaitan
17th July 2007, 10:18
This means that i cant use QcomboBox or other control on a table (item or widget) and a DB?
Could i copy the data from the QTableWidget's model to my own model?? (tableView doesnt support widgets on it, im correct??)

Thx!!

J.

jpn
17th July 2007, 10:30
QTableView uses a delegate and supports widgets just like QTableWidget does. It makes no sense to copy data from an SQL model to QTableWidget when you can simply set the SQL model as QTableView's model and it will show the data for you out of the box. Please take a look at SQL and Model/View examples shipped with Qt.

Shaitan
17th July 2007, 10:34
Thx, copying the model works, but yours is a better solution... ill give it a try!!!
:D

J.