Subclass QItemDelegate not working
-
Hi,
I have the following. My FungusSqlRelationalDelegate.h#ifndef FUNGUSSQLRELATIONALDELEGATE_H #define FUNGUSSQLRELATIONALDELEGATE_H #include <QSqlRelationalDelegate> #include <nulldelegate.h> class FungusSqlRelationalDelegate : public QSqlRelationalDelegate { Q_OBJECT public: explicit FungusSqlRelationalDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *aParent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; }; #endif // FUNGUSSQLRELATIONALDELEGATE_H
And my FungusSqlRelationalDelegate.cpp:
FungusSqlRelationalDelegate::FungusSqlRelationalDelegate(QObject *parent) : QSqlRelationalDelegate (parent) {} QWidget *FungusSqlRelationalDelegate::createEditor(QWidget *aParent, const QStyleOptionViewItem &option, const QModelIndex &index) const { const QSqlRelationalTableModel *sqlModel = qobject_cast<const QSqlRelationalTableModel*>(index.model()); QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0; if (!childModel ) { const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel *>(index.model()); if (proxyModel){ sqlModel = qobject_cast<const QSqlRelationalTableModel *>(proxyModel->sourceModel()); childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0; } } if (!childModel) { return QItemDelegate::createEditor(aParent, option, index); } QComboBox *combo = new QComboBox(aParent); combo->setModel(childModel); combo->setModelColumn(childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn())); combo->installEventFilter(const_cast<FungusSqlRelationalDelegate*>(this)); return combo; } void FungusSqlRelationalDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { if (!index.isValid()) return; QSqlRelationalTableModel *sqlModel = qobject_cast<QSqlRelationalTableModel *>(model); QSortFilterProxyModel *proxyModel = NULL; if (!sqlModel ) { proxyModel = qobject_cast<QSortFilterProxyModel *>(model); if (proxyModel) sqlModel = qobject_cast<QSqlRelationalTableModel *>(proxyModel->sourceModel()); } QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0; QComboBox *combo = qobject_cast<QComboBox *>(editor); if (!childModel || !combo) { QItemDelegate::setModelData(editor, model, index); // HERE I WANT DO THIS: NullDelegate::setModelData(editor, model, index); return; } int currentItem = combo->currentIndex(); int childColIndex = childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn()); int childEditIndex = childModel->fieldIndex(sqlModel->relation(index.column()).indexColumn()); if (proxyModel) { proxyModel->setData(index, childModel->data(childModel->index(currentItem, childEditIndex), Qt::DisplayRole), Qt::DisplayRole); proxyModel->setData(index, childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole), Qt::EditRole); } else { sqlModel->setData(index, childModel->data(childModel->index(currentItem, childColIndex), Qt::DisplayRole), Qt::DisplayRole); sqlModel->setData(index, childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole), Qt::EditRole); } } void FungusSqlRelationalDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QString strVal = ""; const QSqlRelationalTableModel *sqlModel = qobject_cast<const QSqlRelationalTableModel *>(index.model()); if (!sqlModel ) { const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel *>(index.model()); if (proxyModel) { strVal = proxyModel->data(index).toString(); } } else { strVal = sqlModel->data(index).toString(); } QComboBox *combo = qobject_cast<QComboBox *>(editor); if (strVal.isEmpty() || !combo) { QItemDelegate::setEditorData(editor, index); // HERE I WANT DO THIS: NullDelegate::setEditorData(editor, model, index); editor->setProperty("text", index.data()); return; } combo->setCurrentIndex(combo->findText(strVal)); }
In the code you can see my comments "// HERE I WANT DO THIS: NullDelegate::setEditorData(editor, model, index);" and " // HERE I WANT DO THIS: NullDelegate::setModelData(editor, model, index);"
I have created a nulldelegate class this looks like this:
nulldelegate.h
#ifndef NULLDELEGATE_H #define NULLDELEGATE_H #include <QItemDelegate> #include <QStyledItemDelegate> class NullDelegate : public QAbstractItemDelegate { Q_OBJECT public: explicit NullDelegate(QObject *parent = nullptr); void setEditorData(QWidget *editor, const QModelIndex &index) const override ; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; private: }; #endif // NULLDELEGATE_H
and my nulldelegate.cpp
#include "nulldelegate.h" NullDelegate::NullDelegate(QObject *parent) : QItemDelegate(parent) { } void NullDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { editor->setProperty("text", index.data()); } void NullDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { model->setData(index, editor->property("text") == "" ? QVariant() : editor->property("text")); }
My problem now is this:
When I try to call NullDelegate::setModelData(editor, model, index) it tells me the following:
"error: call to non-static member function without an object argument".
Somehow I am too stupid to get this to work. Nulldelegate inherits from QItemDelegate. But in QItemDelegate I didn't find a static setModelData method can someone help me please?
Why did I create a nulldelegate class?
I don't want to insert empty string in my database but store "null" when my QLineEdits are empty. -
Hi,
I have the following. My FungusSqlRelationalDelegate.h#ifndef FUNGUSSQLRELATIONALDELEGATE_H #define FUNGUSSQLRELATIONALDELEGATE_H #include <QSqlRelationalDelegate> #include <nulldelegate.h> class FungusSqlRelationalDelegate : public QSqlRelationalDelegate { Q_OBJECT public: explicit FungusSqlRelationalDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *aParent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; }; #endif // FUNGUSSQLRELATIONALDELEGATE_H
And my FungusSqlRelationalDelegate.cpp:
FungusSqlRelationalDelegate::FungusSqlRelationalDelegate(QObject *parent) : QSqlRelationalDelegate (parent) {} QWidget *FungusSqlRelationalDelegate::createEditor(QWidget *aParent, const QStyleOptionViewItem &option, const QModelIndex &index) const { const QSqlRelationalTableModel *sqlModel = qobject_cast<const QSqlRelationalTableModel*>(index.model()); QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0; if (!childModel ) { const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel *>(index.model()); if (proxyModel){ sqlModel = qobject_cast<const QSqlRelationalTableModel *>(proxyModel->sourceModel()); childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0; } } if (!childModel) { return QItemDelegate::createEditor(aParent, option, index); } QComboBox *combo = new QComboBox(aParent); combo->setModel(childModel); combo->setModelColumn(childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn())); combo->installEventFilter(const_cast<FungusSqlRelationalDelegate*>(this)); return combo; } void FungusSqlRelationalDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { if (!index.isValid()) return; QSqlRelationalTableModel *sqlModel = qobject_cast<QSqlRelationalTableModel *>(model); QSortFilterProxyModel *proxyModel = NULL; if (!sqlModel ) { proxyModel = qobject_cast<QSortFilterProxyModel *>(model); if (proxyModel) sqlModel = qobject_cast<QSqlRelationalTableModel *>(proxyModel->sourceModel()); } QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0; QComboBox *combo = qobject_cast<QComboBox *>(editor); if (!childModel || !combo) { QItemDelegate::setModelData(editor, model, index); // HERE I WANT DO THIS: NullDelegate::setModelData(editor, model, index); return; } int currentItem = combo->currentIndex(); int childColIndex = childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn()); int childEditIndex = childModel->fieldIndex(sqlModel->relation(index.column()).indexColumn()); if (proxyModel) { proxyModel->setData(index, childModel->data(childModel->index(currentItem, childEditIndex), Qt::DisplayRole), Qt::DisplayRole); proxyModel->setData(index, childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole), Qt::EditRole); } else { sqlModel->setData(index, childModel->data(childModel->index(currentItem, childColIndex), Qt::DisplayRole), Qt::DisplayRole); sqlModel->setData(index, childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole), Qt::EditRole); } } void FungusSqlRelationalDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QString strVal = ""; const QSqlRelationalTableModel *sqlModel = qobject_cast<const QSqlRelationalTableModel *>(index.model()); if (!sqlModel ) { const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel *>(index.model()); if (proxyModel) { strVal = proxyModel->data(index).toString(); } } else { strVal = sqlModel->data(index).toString(); } QComboBox *combo = qobject_cast<QComboBox *>(editor); if (strVal.isEmpty() || !combo) { QItemDelegate::setEditorData(editor, index); // HERE I WANT DO THIS: NullDelegate::setEditorData(editor, model, index); editor->setProperty("text", index.data()); return; } combo->setCurrentIndex(combo->findText(strVal)); }
In the code you can see my comments "// HERE I WANT DO THIS: NullDelegate::setEditorData(editor, model, index);" and " // HERE I WANT DO THIS: NullDelegate::setModelData(editor, model, index);"
I have created a nulldelegate class this looks like this:
nulldelegate.h
#ifndef NULLDELEGATE_H #define NULLDELEGATE_H #include <QItemDelegate> #include <QStyledItemDelegate> class NullDelegate : public QAbstractItemDelegate { Q_OBJECT public: explicit NullDelegate(QObject *parent = nullptr); void setEditorData(QWidget *editor, const QModelIndex &index) const override ; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; private: }; #endif // NULLDELEGATE_H
and my nulldelegate.cpp
#include "nulldelegate.h" NullDelegate::NullDelegate(QObject *parent) : QItemDelegate(parent) { } void NullDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { editor->setProperty("text", index.data()); } void NullDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { model->setData(index, editor->property("text") == "" ? QVariant() : editor->property("text")); }
My problem now is this:
When I try to call NullDelegate::setModelData(editor, model, index) it tells me the following:
"error: call to non-static member function without an object argument".
Somehow I am too stupid to get this to work. Nulldelegate inherits from QItemDelegate. But in QItemDelegate I didn't find a static setModelData method can someone help me please?
Why did I create a nulldelegate class?
I don't want to insert empty string in my database but store "null" when my QLineEdits are empty.@Gabber said in Subclass QItemDelegate not working:
When I try to call NullDelegate::setModelData(editor, model, index) it tells me the following:
You need an instance of
NullDelegate
to call it on. -
@JonB said in Subclass QItemDelegate not working:
You need an instance of NullDelegate to call it on.
Oddly enough, this had not worked for two days....
Unfortunately, my NullDelegate still does not work. Maybe you can help me. I am with my beginner knowledge unfortunately at the end and also do not know for what I can still look...
Here again some info why I derived this from QItemDelegate. In my code example above, a QItemDelegate::setModelData is called, so I thought I have to derive from QItemDelegate. If I am wrong please correct me.
The next info that is important to implement this is the following. I want to insert "NULL" into my database if my QLineEdit or my QPlainTextEdit is empty. You had sent me this link once.
What have I already been able to find out?
To get the data from the widget QPlainTextEdit you have to use the property("plainText") instead of property("text") to display the data. Unfortunately the paste and paste NULL does not work.
I would need urgent help or tips.
Thanks :)
-
I have been able to find out something. My setModelData from NullDelegate looks like this:
void NullDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { const QVariant textWidget = editor->property("text"); if(textWidget.isValid()){ model->setData(index, editor->property("text") == "" ? QVariant() : editor->property("text")); } else { model->setData(index, editor->property("plainText") == "" ? QVariant() : editor->property("plainText")); } }
Now I can save my data to the database except when my QLineEdit is empty. It does not want to save that to the database. Strangely enough, it works fine with my QPlainTextEdit. If there is something in this field it is saved, if I delete the content from QPlainTextEdit it saves "NULL" to the database.
Any Idea?
-
I have found the error. The error was in the database. Here "not null" was set. The following code now works as expected:
void NullDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { const QByteArray name = editor->metaObject()->userProperty().name(); if(!name.isEmpty()){ if(editor->property(name).toString().isEmpty()){ model->setData(index, QVariant(), Qt::EditRole); } else { model->setData(index, editor->property(name), Qt::EditRole); } }
void NullDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QVariant data = index.data(Qt::EditRole); const QByteArray name = editor->metaObject()->userProperty().name(); if (!name.isEmpty()) { if (!data.isValid()) data = QVariant(editor->property(name).userType(), (const void *)0); editor->setProperty(name, data); } }