/*! \reimp
*/
Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const
{
    Q_D(const QSqlTableModel);
    if (index.internalPointer() || index.column() < 0 || index.column() >= d->rec.count()
        || index.row() < 0)
        return 0;

    bool editable = true;

    if (d->rec.field(index.column()).isReadOnly()) {
        editable = false;
    }
    else {
        const QSqlTableModelPrivate::ModifiedRow mrow = d->cache.value(index.row());
        if (mrow.op() == QSqlTableModelPrivate::Delete) {
            editable = false;
        }
        else if (d->strategy == OnFieldChange) {
            if (mrow.op() != QSqlTableModelPrivate::Insert)
                if (!isDirty(index) && isDirty())
                    editable = false;
        }
        else if (d->strategy == OnRowChange) {
            if (mrow.submitted() && isDirty())
                editable = false;
        }
    }

    if (!editable)
        return QSqlQueryModel::flags(index);
    else
        return QSqlQueryModel::flags(index) | Qt::ItemIsEditable;
}
/*!
    Returns \c true if the value at the index \a index is dirty, otherwise false.
    Dirty values are values that were modified in the model
    but not yet written into the database.

    If \a index is invalid or points to a non-existing row, false is returned.
*/
bool QSqlTableModel::isDirty(const QModelIndex &index) const
{
    Q_D(const QSqlTableModel);
    if (!index.isValid())
        return false;

    const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
    if (row.submitted())
        return false;

    return row.op() == QSqlTableModelPrivate::Insert
           || row.op() == QSqlTableModelPrivate::Delete
           || (row.op() == QSqlTableModelPrivate::Update
               && row.rec().isGenerated(index.column()));
}