Solved Editing data in QStandardItemModel with tableView
-
Hi,
I have a working QStandardItemModel with tableView. Editing small fields with QLineEdit works fine. But I also have a date field. I used the following code to place a calendar widget in the field:QDateTimeEdit *editor = new QDateTimeEdit(parent); editor->setDisplayFormat ("dd/M/yyyy"); editor->setCalendarPopup (true); connect(editor,&QDateTimeEdit::editingFinished ,this,&myDelegate::commitAndCloseEditor ); return editor;
It works great, but the calendar widget shows up in the top left corner of the dialog. Please help me to figure out how to keep it around the column which holds the dates.
Thank you for your help. -
@gabor53
i assume you are in your delegates createEditor() method?
If so there is aQStyleOptionViewItem
parameter passed, which has arect
member.
Either move it to the rect's top-left or assign the rect to the editor directly. -
I implemented something identical and never had any similar problem. here is my code (i use QDateEdit instead of QDateTimeEdit)
datedelegate.h
#ifndef DATEDELEGATE_H #define DATEDELEGATE_H #include <QStyledItemDelegate> class QDate; class DateDelegatePrivate; class DateDelegate : public QStyledItemDelegate { Q_OBJECT Q_DECLARE_PRIVATE(DateDelegate) public: explicit DateDelegate(QObject *parent=nullptr); virtual ~DateDelegate(); DateDelegate(const DateDelegate&) = delete; DateDelegate& operator=(const DateDelegate&) = delete; virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; virtual void setEditorData(QWidget *editor, const QModelIndex &index) const override; virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setCalendarPopup(bool val); bool calendarPopup() const; void setMaximumDate(const QDate& val); void setMinimumDate(const QDate& val); const QDate& maximumDate() const; const QDate& minimumDate() const; private: DateDelegatePrivate* d_ptr; }; #endif // DATEDELEGATE_H
datedelegate.cpp
#include "datedelegate.h" #include <QDateEdit> #include <QApplication> class DateDelegatePrivate{ Q_DECLARE_PUBLIC(DateDelegate) DateDelegatePrivate(DateDelegate* q); DateDelegatePrivate() = delete; DateDelegate* q_ptr; bool m_calendarPopUp; QDate m_minDate; QDate m_maxDate; }; DateDelegatePrivate::DateDelegatePrivate(DateDelegate* q) :q_ptr(q) , m_calendarPopUp(true) { } DateDelegate::DateDelegate(QObject *parent) : QStyledItemDelegate(parent) , d_ptr(new DateDelegatePrivate(this)) { } DateDelegate::~DateDelegate() { delete d_ptr; } QWidget * DateDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { QDateEdit* result = new QDateEdit(parent); result->setCalendarPopup(calendarPopup()); result->setMaximumDate(maximumDate()); result->setMinimumDate(minimumDate()); return result; } void DateDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QDateEdit* dtEditor = qobject_cast<QDateEdit*>(editor); Q_ASSERT(dtEditor); if (index.data(Qt::EditRole).isNull()) dtEditor->clear(); else dtEditor->setDate(index.data(Qt::EditRole).toDate()); } void DateDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QDateEdit* dtEditor = qobject_cast<QDateEdit*>(editor); if(dtEditor->text().isEmpty()) model->setData(index, QVariant(), Qt::EditRole); else model->setData(index, dtEditor->date(), Qt::EditRole); } void DateDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const { editor->setGeometry(option.rect); } QSize DateDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { QVariant value = index.data(Qt::SizeHintRole); if (value.isValid()) return qvariant_cast<QSize>(value); QStyleOptionViewItem opt = option; initStyleOption(&opt, index); const QWidget *widget = option.widget; const QStyle *style = widget ? widget->style() : QApplication::style(); const QSize hint = style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), widget); QSize resultSize; Q_D(const DateDelegate); #ifdef Q_OS_MAC if (d->m_calendarPopUp) { QStyleOptionComboBox opt; resultSize = style->sizeFromContents(QStyle::CT_ComboBox, &opt, hint, widget); } else #endif { QStyleOptionSpinBox opt; if (d->m_calendarPopUp) { opt.subControls = QStyle::SC_ComboBoxFrame | QStyle::SC_ComboBoxEditField | QStyle::SC_ComboBoxArrow; } resultSize = style->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, widget).expandedTo(QApplication::globalStrut()); } return resultSize; } void DateDelegate::setCalendarPopup(bool val) { Q_D(DateDelegate); d->m_calendarPopUp = val; } bool DateDelegate::calendarPopup() const { Q_D(const DateDelegate); return d->m_calendarPopUp; } void DateDelegate::setMaximumDate(const QDate& val) { Q_D(DateDelegate); d->m_maxDate = val; } void DateDelegate::setMinimumDate(const QDate& val) { Q_D(DateDelegate); d->m_minDate = val; } const QDate& DateDelegate::maximumDate() const { Q_D(const DateDelegate); return d->m_maxDate; } const QDate& DateDelegate::minimumDate() const { Q_D(const DateDelegate); return d->m_minDate; }
-
@raven-worx
Yes, you are right. -
@gabor53
anyway the more correct way is like in the example posted by @VRoninvoid DateDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const { editor->setGeometry(option.rect); }
Since i am not sure in which cases the editor's geometry needs to be updated. This way we trust Qt.
-
@raven-worx
Thank you. This worked out well. I ended up usingvoid myDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry (option.rect); }