Advise: QComboBox delegate which will take its dataset from QSqlQueryModel
-
Hello.
I am "on my way":http://qt-project.org/forums/viewthread/31269/ to understanding how delegates work.
Right now, I wanted to implement a QComboBox based delegate that will work on QTableView cells (not that that's relevant, I guess). The important bit is that it will take its dataset from a QSqlQueryModel.
So far, the autocompletion and the combobox seems to be working, but I can't avoid the feeling of not having done something "the right way(TM)".
I'll show you my code.
[code]
#ifndef COMPLETIONDELEGATE_H
#define COMPLETIONDELEGATE_H#include <QItemDelegate>
#include <QtSql/QSqlQueryModel>class CompletionDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit CompletionDelegate(QObject *parent = 0, QSqlQueryModel *model = NULL);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;
signals:
public slots:
private:
QSqlQueryModel *model;};
#endif // COMPLETIONDELEGATE_H
[/code][code]
#include "completiondelegate.h"
#include <QComboBox>
#include <QtSql/QSqlQueryModel>
#include <QDebug>
#include <QtSql/QSqlRecord>
#include <QtSql/QSqlQuery>
#include <QCompleter>CompletionDelegate::CompletionDelegate(QObject *parent, QSqlQueryModel *mdl) :
QItemDelegate(parent)
{
model = mdl;
qDebug() << Q_FUNC_INFO << "we are building this";
while(mdl->query().next())
qDebug() << Q_FUNC_INFO << model->query().value(0);
}QWidget CompletionDelegate::createEditor(QWidget parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
//const QAbstractItemModel model = index.model();
if (!model)
{
return QItemDelegate::createEditor(parent, option, index);
}
QComboBox box = new QComboBox(parent);
box->setEditable(true);
box->setAutoCompletion(true);
//box->setModel(const_cast<QAbstractItemModel>(model));
box->setModel(model);
//box->setModelColumn(index.column());
box->setModelColumn(0);
box->completer()->setCompletionMode(QCompleter::PopupCompletion);
box->installEventFilter(const_cast<CompletionDelegate>(this));
return box;
}void CompletionDelegate::setEditorData(QWidget* editor, const QModelIndex & index ) const
{
QComboBox* box = qobject_cast<QComboBox*>(editor);
const QAbstractItemModel *model = index.model();
if (!box || !model)
{
QItemDelegate::setEditorData(editor, index);
}
box->setCurrentIndex(index.row());
}void CompletionDelegate::setModelData(QWidget editor, QAbstractItemModel model, const QModelIndex &index) const
{
if (!index.isValid())
return;
QComboBox box = qobject_cast<QComboBox>(editor);
if (!box)
return QItemDelegate::setModelData(editor, model, index);
model->setData(index, box->currentText(), Qt::DisplayRole);
model->setData(index, box->currentText(), Qt::EditRole);
}
[/code]Then, I use it like this:
[code]
QSqlQueryModel *mdl_articulos = new QSqlQueryModel;
mdl_articulos->setQuery("SELECT ref,desc,pvp FROM articulos;");
ui->tableView_cascosYAccesorios->setItemDelegateForColumn(2, new CompletionDelegate(this, mdl_articulos));
[/code]That's a QTableView, as said above.
When I say that I have a feeling of having done something wrong I am talking specifically about passing the pointer to QSqlQueryModel as an argument to this class. Is that ok or is there a better way? I still don't understand properly what QModelIndex'es are, so I might be duplicating something... I see that all the typical functions that people reimplement in this class work with indexes so...
How would you go about this?
Of course, feel free to criticise any other part of the code...
Thank you for your comments.