1

I have a QTableView displaying a table using a QSqlTableModel. In that table, I have a DATETIME column. When I add a line and try to edit that column, I have a simple QEdit. I would like to have a QDateTimeEdit (or similar) there, it would be much much easier to edit that field correctly.

As I understood the documentation, it should work by itself, the default delegate should be able to handle QDateTime and put a QDateTimeEdit, so I guess the QSqlTableModel didn't recognize it as a date, since the table is empty. Is there an easy way to specify that it is a date and not just text ?

I am using SQlite as database for now, I don't know if that could be the problem ? I don't know what piece of code I could paste here that would be relevant, it's really just a QSqlTableModel::setTable and a QTableView::setModel, nothing much.

Nejat
  • 31,784
  • 12
  • 106
  • 138
Ulrar
  • 895
  • 8
  • 17

2 Answers2

2

SQLite uses a dynamic type system i.e. it has no data types. You should implement a custom delegate and set it manually.

Custom delegate for QDateTimeEdit:

#include <QItemDelegate>
#include <QDateTimeEdit>

class DateTimeEditDelegate: public QItemDelegate
{
 Q_OBJECT
public:
    DateTimeEditDelegate(QObject *parent = 0);

    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;

    void updateEditorGeometry( QWidget *editor,
                            const QStyleOptionViewItem &option,
                            const QModelIndex &index ) const;

    mutable QDateTimeEdit *dataTimeEdit;

private slots:

    void setData(QDateTime val);

};



DateTimeEditDelegate::DateTimeEditDelegate(QObject *parent ):QItemDelegate(parent)
{

}

QWidget *DateTimeEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    dataTimeEdit = new QDateTimeEdit( parent );
    QObject::connect(dataTimeEdit,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(setData(QDateTime)));
    return dataTimeEdit;
}

void DateTimeEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QVariant dateTime = index.model()->data( index, Qt::DisplayRole );

    (static_cast<QDateTimeEdit*>( editor ))->setDateTime(dateTime.toDateTime());
}

void DateTimeEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    model->setData( index, static_cast<QDateTimeEdit*>( editor )->dateTime() );
}


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

void DateTimeEditDelegate::setData(QDateTime val)
{
    emit commitData(dataTimeEdit);
}

You can set an instance of the delegate to a column:

ui->tableView->setItemDelegateForColumn(0, new DateTimeEditDelegate(ui->tableView));
Nejat
  • 31,784
  • 12
  • 106
  • 138
  • That doesn't work, setItemDelegateForColumn takes a QAbstractItemDelegate, so I guess I'd have to somehow reimplement that – Ulrar Mar 29 '14 at 20:44
  • 1
    It works for one cell, I guess if setting the delegate for one item at a time it would work fine. Thanks, I created my own delegate for setItemDelegateForColumn – Ulrar Mar 30 '14 at 10:08
1

Managed to resolve that by implementing a Delegate. There is the code if someone needs it someday.

#ifndef                 DATEDELEGATE_HH__
# define                DATEDELEGATE_HH__

# include               <QItemDelegate>
# include               <QDateTimeEdit>

class                   DateDelegate : public QItemDelegate
{
public:
                        DateDelegate(QWidget *parent = 0);
  virtual               ~DateDelegate(void);

  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;
};

#endif

`

#include                "DateDelegate.hh"

DateDelegate::DateDelegate(QWidget *parent)
  : QItemDelegate(parent)
{
}

DateDelegate::~DateDelegate(void)
{
}

QWidget                 *DateDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
  QDateTimeEdit         *editor = new QDateTimeEdit(parent);

  editor->setCalendarPopup(true);
  editor->setDateTime(QDateTime::fromString(index.data().toString(), "dd/MM/yyyy hh:mm:ss"));
  editor->setDisplayFormat("dd/mm/yyyy");
  return (editor);
}

void                    DateDelegate::setEditorData(QWidget *paramEditor, const QModelIndex &index) const
{
  QDateTimeEdit         *editor = static_cast<QDateTimeEdit *>(paramEditor);

  editor->setDateTime(QDateTime::fromString(index.data().toString(), "dd/MM/yyyy hh:mm:ss"));
}

void                    DateDelegate::setModelData(QWidget *paramEditor, QAbstractItemModel *model, const QModelIndex& index) const
{
  QDateTimeEdit         *editor = static_cast<QDateTimeEdit *>(paramEditor);

  model->setData(index, editor->dateTime().toString("dd/MM/yyyy hh:mm:ss"));
}

Then I just use this->ui->tableView->setItemDelegateForColumn(4, new DateDelegate(this->ui->tableView)); to use it. I'm still having some strange problem from time to time, like a random cell will take the value of the cell I'm editing, I'm trying to figure out why.

Ulrar
  • 895
  • 8
  • 17