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.


  • Moderators

    @gabor53
    i assume you are in your delegates createEditor() method?
    If so there is a QStyleOptionViewItem parameter passed, which has a rect 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.


  • Moderators

    @gabor53
    anyway the more correct way is like in the example posted by @VRonin

    void 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 using

    void myDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        editor->setGeometry (option.rect);
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.