/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qqmltablemodel_p.h"

#include <QtCore/qloggingcategory.h>
#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmlengine.h>

QT_BEGIN_NAMESPACE

Q_LOGGING_CATEGORY(lcTableModel, "qt.qml.tablemodel")

/*!
    \qmltype TableModel
    \instantiates QQmlTableModel
    \inqmlmodule Qt.labs.qmlmodels
    \brief Encapsulates a simple table model.
    \since 5.14

    The TableModel type stores JavaScript/JSON objects as data for a table
    model that can be used with \l TableView. It is intended to support
    very simple models without requiring the creation of a custom
    QAbstractTableModel subclass in C++.

    \snippet qml/tablemodel/fruit-example-simpledelegate.qml file

    The model's initial row data is set with either the \l rows property or by
    calling \l appendRow(). Each column in the model is specified by declaring
    a \l TableModelColumn instance, where the order of each instance determines
    its column index. Once the model's \l Component::completed() signal has been
    emitted, the columns and roles will have been established and are then
    fixed for the lifetime of the model.

    To access a specific row, the \l getRow() function can be used.
    It's also possible to access the model's JavaScript data
    directly via the \l rows property, but it is not possible to
    modify the model data this way.

    To add new rows, use \l appendRow() and \l insertRow(). To modify
    existing rows, use \l setRow(), \l moveRow(), \l removeRow(), and
    \l clear().

    It is also possible to modify the model's data via the delegate,
    as shown in the example above:

    \snippet qml/tablemodel/fruit-example-simpledelegate.qml delegate

    If the type of the data at the modified role does not match the type of the
    data that is set, it will be automatically converted via
    \l {QVariant::canConvert()}{QVariant}.

    \section1 Supported Row Data Structures

    TableModel is designed to work with JavaScript/JSON data, where each row
    is a simple key-pair object:

    \code
    {
        // Each property is one cell/column.
        checked: false,
        amount: 1,
        fruitType: "Apple",
        fruitName: "Granny Smith",
        fruitPrice: 1.50
    },
    // ...
    \endcode

    As model manipulation in Qt is done via row and column indices,
    and because object keys are unordered, each column must be specified via
    TableModelColumn. This allows mapping Qt's built-in roles to any property
    in each row object.

    Complex row structures are supported, but with limited functionality.
    As TableModel has no way of knowing how each row is structured,
    it cannot manipulate it. As a consequence of this, the copy of the
    model data that TableModel has stored in \l rows is not kept in sync
    with the source data that was set in QML. For these reasons, TableModel
    relies on the user to handle simple data manipulation.

    For example, suppose you wanted to have several roles per column. One way
    of doing this is to use a data source where each row is an array and each
    cell is an object. To use this data source with TableModel, define a
    getter and setter:

    \code
    TableModel {
        TableModelColumn {
            display: function(modelIndex) { return rows[modelIndex.row][0].checked }
            setDisplay: function(modelIndex, cellData) { rows[modelIndex.row][0].checked = cellData }
        }
        // ...

        rows: [
            [
                { checked: false, checkable: true },
                { amount: 1 },
                { fruitType: "Apple" },
                { fruitName: "Granny Smith" },
                { fruitPrice: 1.50 }
            ]
            // ...
        ]
    }
    \endcode

    The row above is one example of a complex row.

    \note Row manipulation functions such as \l appendRow(), \l removeRow(),
    etc. are not supported when using complex rows.

    \section1 Using DelegateChooser with TableModel

    For most real world use cases, it is recommended to use DelegateChooser
    as the delegate of a TableView that uses TableModel. This allows you to
    use specific roles in the relevant delegates. For example, the snippet
    above can be rewritten to use DelegateChooser like so:

    \snippet qml/tablemodel/fruit-example-delegatechooser.qml file

    The most specific delegates are declared first: the columns at index \c 0
    and \c 1 have \c bool and \c integer data types, so they use a
    \l [QtQuickControls2]{CheckBox} and \l [QtQuickControls2]{SpinBox},
    respectively. The remaining columns can simply use a
    \l [QtQuickControls2]{TextField}, and so that delegate is declared
    last as a fallback.

    \sa TableModelColumn, TableView, QAbstractTableModel
*/

QQmlTableModel::QQmlTableModel(QObject *parent)
    : QAbstractTableModel(parent)
{
}

QQmlTableModel::~QQmlTableModel()
{
}

/*!
    \qmlproperty object TableModel::rows

    This property holds the model data in the form of an array of rows:

    \snippet qml/tablemodel/fruit-example-simpledelegate.qml rows

    \sa getRow(), setRow(), moveRow(), appendRow(), insertRow(), clear(), rowCount, columnCount
*/
QVariant QQmlTableModel::rows() const
{
    return mRows;
}

void QQmlTableModel::setRows(const QVariant &rows)
{
    if (rows.userType() != qMetaTypeId<QJSValue>()) {
        qmlWarning(this) << "setRows(): \"rows\" must be an array; actual type is " << rows.typeName();
        return;
    }

    const QJSValue rowsAsJSValue = rows.value<QJSValue>();
    const QVariantList rowsAsVariantList = rowsAsJSValue.toVariant().toList();
    if (rowsAsVariantList == mRows) {
        // No change.
        return;
    }

    if (!componentCompleted) {
        // Store the rows until we can call doSetRows() after component completion.
        mRows = rowsAsVariantList;
        return;
    }

    doSetRows(rowsAsVariantList);
}

void QQmlTableModel::doSetRows(const QVariantList &rowsAsVariantList)
{
    Q_ASSERT(componentCompleted);

    // By now, all TableModelColumns should have been set.
    if (mColumns.isEmpty()) {
        qmlWarning(this) << "No TableModelColumns were set; model will be empty";
        return;
    }

    const bool firstTimeValidRowsHaveBeenSet = mColumnMetadata.isEmpty();
    if (!firstTimeValidRowsHaveBeenSet) {
        // This is not the first time rows have been set; validate each one.
        for (int rowIndex = 0; rowIndex < rowsAsVariantList.size(); ++rowIndex) {
            // validateNewRow() expects a QVariant wrapping a QJSValue, so to
            // simplify the code, just create one here.
            const QVariant row = QVariant::fromValue(rowsAsVariantList.at(rowIndex));
            if (!validateNewRow("setRows()", row, rowIndex, SetRowsOperation))
                return;
        }
    }

    const int oldRowCount = mRowCount;
    const int oldColumnCount = mColumnCount;

    beginResetModel();

    // We don't clear the column or role data, because a TableModel should not be reused in that way.
    // Once it has valid data, its columns and roles are fixed.
    mRows = rowsAsVariantList;
    mRowCount = mRows.size();

    // Gather metadata the first time rows is set.
    if (firstTimeValidRowsHaveBeenSet && !mRows.isEmpty())
        fetchColumnMetadata();

    endResetModel();

    emit rowsChanged();

    if (mRowCount != oldRowCount)
        emit rowCountChanged();
    if (mColumnCount != oldColumnCount)
        emit columnCountChanged();
}

QQmlTableModel::ColumnRoleMetadata QQmlTableModel::fetchColumnRoleData(const QString &roleNameKey,
    QQmlTableModelColumn *tableModelColumn, int columnIndex) const
{
    const QVariant firstRow = mRows.first();
    ColumnRoleMetadata roleData;

    QJSValue columnRoleGetter = tableModelColumn->getterAtRole(roleNameKey);
    if (columnRoleGetter.isUndefined()) {
        // This role is not defined, which is fine; just skip it.
        return roleData;
    }

    if (columnRoleGetter.isString()) {
        // The role is set as a string, so we assume the row is a simple object.
        if (firstRow.type() != QVariant::Map) {
            qmlWarning(this).quote() << "expected row for role "
                << roleNameKey << " of TableModelColumn at index "
                << columnIndex << " to be a simple object, but it's "
                << firstRow.typeName() << " instead: " << firstRow;
            return roleData;
        }
        const QVariantMap firstRowAsMap = firstRow.toMap();
        const QString rolePropertyName = columnRoleGetter.toString();
        const QVariant roleProperty = firstRowAsMap.value(rolePropertyName);

        roleData.isStringRole = true;
        roleData.name = rolePropertyName;
        roleData.type = roleProperty.type();
        roleData.typeName = QString::fromLatin1(roleProperty.typeName());
    } else if (columnRoleGetter.isCallable()) {
        // The role is provided via a function, which means the row is complex and
        // the user needs to provide the data for it.
        const auto modelIndex = index(0, columnIndex);
        const auto args = QJSValueList() << qmlEngine(this)->toScriptValue(modelIndex);
        const QVariant cellData = columnRoleGetter.call(args).toVariant();

        // We don't know the property name since it's provided through the function.
        // roleData.name = ???
        roleData.isStringRole = false;
        roleData.type = cellData.type();
        roleData.typeName = QString::fromLatin1(cellData.typeName());
    } else {
        // Invalid role.
        qmlWarning(this) << "TableModelColumn role for column at index "
            << columnIndex << " must be either a string or a function; actual type is: "
            << columnRoleGetter.toString();
    }

    return roleData;
}

void QQmlTableModel::fetchColumnMetadata()
{
    qCDebug(lcTableModel) << "gathering metadata for" << mColumnCount << "columns from first row:";

    static const auto supportedRoleNames = QQmlTableModelColumn::supportedRoleNames();

    // Since we support different data structures at the row level, we require that there
    // is a TableModelColumn for each column.
    // Collect and cache metadata for each column. This makes data lookup faster.
    for (int columnIndex = 0; columnIndex < mColumns.size(); ++columnIndex) {
        QQmlTableModelColumn *column = mColumns.at(columnIndex);
        qCDebug(lcTableModel).nospace() << "- column " << columnIndex << ":";

        ColumnMetadata metaData;
        const auto builtInRoleKeys = supportedRoleNames.keys();
        for (const int builtInRoleKey : builtInRoleKeys) {
            const QString builtInRoleName = supportedRoleNames.value(builtInRoleKey);
            ColumnRoleMetadata roleData = fetchColumnRoleData(builtInRoleName, column, columnIndex);
            if (roleData.type == QVariant::Invalid) {
                // This built-in role was not specified in this column.
                continue;
            }

            qCDebug(lcTableModel).nospace() << "  - added metadata for built-in role "
                << builtInRoleName << " at column index " << columnIndex
                << ": name=" << roleData.name << " typeName=" << roleData.typeName
                << " type=" << roleData.type;

            // This column now supports this specific built-in role.
            metaData.roles.insert(builtInRoleName, roleData);
            // Add it if it doesn't already exist.
            mRoleNames[builtInRoleKey] = builtInRoleName.toLatin1();
        }
        mColumnMetadata.insert(columnIndex, metaData);
    }
}

/*!
    \qmlmethod TableModel::appendRow(object row)

    Adds a new row to the end of the model, with the
    values (cells) in \a row.

    \code
        model.appendRow({
            checkable: true,
            amount: 1,
            fruitType: "Pear",
            fruitName: "Williams",
            fruitPrice: 1.50,
        })
    \endcode

    \sa insertRow(), setRow(), removeRow()
*/
void QQmlTableModel::appendRow(const QVariant &row)
{
    if (!validateNewRow("appendRow()", row, -1, AppendOperation))
        return;

    doInsert(mRowCount, row);
}

/*!
    \qmlmethod TableModel::clear()

    Removes all rows from the model.

    \sa removeRow()
*/
void QQmlTableModel::clear()
{
    QQmlEngine *engine = qmlEngine(this);
    Q_ASSERT(engine);
    setRows(QVariant::fromValue(engine->newArray()));
}

/*!
    \qmlmethod object TableModel::getRow(int rowIndex)

    Returns the row at \a rowIndex in the model.

    Note that this equivalent to accessing the row directly
    through the \l rows property:

    \code
    Component.onCompleted: {
        // These two lines are equivalent.
        console.log(model.getRow(0).display);
        console.log(model.rows[0].fruitName);
    }
    \endcode

    \note the returned object cannot be used to modify the contents of the
    model; use setRow() instead.

    \sa setRow(), appendRow(), insertRow(), removeRow(), moveRow()
*/
QVariant QQmlTableModel::getRow(int rowIndex)
{
    if (!validateRowIndex("getRow()", "rowIndex", rowIndex))
        return QVariant();

    return mRows.at(rowIndex);
}

/*!
    \qmlmethod TableModel::insertRow(int rowIndex, object row)

    Adds a new row to the list model at position \a rowIndex, with the
    values (cells) in \a row.

    \code
        model.insertRow(2, {
            checkable: true, checked: false,
            amount: 1,
            fruitType: "Pear",
            fruitName: "Williams",
            fruitPrice: 1.50,
        })
    \endcode

    The \a rowIndex must be to an existing item in the list, or one past
    the end of the list (equivalent to \l appendRow()).

    \sa appendRow(), setRow(), removeRow(), rowCount
*/
void QQmlTableModel::insertRow(int rowIndex, const QVariant &row)
{
    if (!validateNewRow("insertRow()", row, rowIndex))
        return;

    doInsert(rowIndex, row);
}

void QQmlTableModel::doInsert(int rowIndex, const QVariant &row)
{
    beginInsertRows(QModelIndex(), rowIndex, rowIndex);

    // Adding rowAsVariant.toList() will add each invidual variant in the list,
    // which is definitely not what we want.
    const QVariant rowAsVariant = row.value<QJSValue>().toVariant();
    mRows.insert(rowIndex, rowAsVariant);
    ++mRowCount;

    qCDebug(lcTableModel).nospace() << "inserted the following row to the model at index "
        << rowIndex << ":\n" << rowAsVariant.toMap();

    // Gather metadata the first time a row is added.
    if (mColumnMetadata.isEmpty())
        fetchColumnMetadata();

    endInsertRows();
    emit rowCountChanged();
}

void QQmlTableModel::classBegin()
{
}

void QQmlTableModel::componentComplete()
{
    componentCompleted = true;

    mColumnCount = mColumns.size();
    if (mColumnCount > 0)
        emit columnCountChanged();

    doSetRows(mRows);
}

/*!
    \qmlmethod TableModel::moveRow(int fromRowIndex, int toRowIndex, int rows)

    Moves \a rows from the index at \a fromRowIndex to the index at
    \a toRowIndex.

    The from and to ranges must exist; for example, to move the first 3 items
    to the end of the list:

    \code
        model.moveRow(0, model.rowCount - 3, 3)
    \endcode

    \sa appendRow(), insertRow(), removeRow(), rowCount
*/
void QQmlTableModel::moveRow(int fromRowIndex, int toRowIndex, int rows)
{
    if (fromRowIndex == toRowIndex) {
        qmlWarning(this) << "moveRow(): \"fromRowIndex\" cannot be equal to \"toRowIndex\"";
        return;
    }

    if (rows <= 0) {
        qmlWarning(this) << "moveRow(): \"rows\" is less than or equal to 0";
        return;
    }

    if (!validateRowIndex("moveRow()", "fromRowIndex", fromRowIndex))
        return;

    if (!validateRowIndex("moveRow()", "toRowIndex", toRowIndex))
        return;

    if (fromRowIndex + rows > mRowCount) {
        qmlWarning(this) << "moveRow(): \"fromRowIndex\" (" << fromRowIndex
            << ") + \"rows\" (" << rows << ") = " << (fromRowIndex + rows)
            << ", which is greater than rowCount() of " << mRowCount;
        return;
    }

    if (toRowIndex + rows > mRowCount) {
        qmlWarning(this) << "moveRow(): \"toRowIndex\" (" << toRowIndex
            << ") + \"rows\" (" << rows << ") = " << (toRowIndex + rows)
            << ", which is greater than rowCount() of " << mRowCount;
        return;
    }

    qCDebug(lcTableModel).nospace() << "moving " << rows
        << " row(s) from index " << fromRowIndex
        << " to index " << toRowIndex;

    // Based on the same call in QQmlListModel::moveRow().
    beginMoveRows(QModelIndex(), fromRowIndex, fromRowIndex + rows - 1, QModelIndex(),
        toRowIndex > fromRowIndex ? toRowIndex + rows : toRowIndex);

    // Based on ListModel::moveRow().
    if (fromRowIndex > toRowIndex) {
        // Only move forwards - flip if moving backwards.
        const int from = fromRowIndex;
        const int to = toRowIndex;
        fromRowIndex = to;
        toRowIndex = to + rows;
        rows = from - to;
    }

    QVector<QVariant> store;
    store.reserve(rows);
    for (int i = 0; i < (toRowIndex - fromRowIndex); ++i)
        store.append(mRows.at(fromRowIndex + rows + i));
    for (int i = 0; i < rows; ++i)
        store.append(mRows.at(fromRowIndex + i));
    for (int i = 0; i < store.size(); ++i)
        mRows[fromRowIndex + i] = store[i];

    qCDebug(lcTableModel).nospace() << "after moving, rows are:\n" << mRows;

    endMoveRows();
}

/*!
    \qmlmethod TableModel::removeRow(int rowIndex, int rows = 1)

    Removes the row at \a rowIndex from the model.

    \sa clear(), rowCount
*/
void QQmlTableModel::removeRow(int rowIndex, int rows)
{
    if (!validateRowIndex("removeRow()", "rowIndex", rowIndex))
        return;

    if (rows <= 0) {
        qmlWarning(this) << "removeRow(): \"rows\" is less than or equal to zero";
        return;
    }

    if (rowIndex + rows - 1 >= mRowCount) {
        qmlWarning(this) << "removeRow(): \"rows\" " << rows
            << " exceeds available rowCount() of " << mRowCount
            << " when removing from \"rowIndex\" " << rowIndex;
        return;
    }

    beginRemoveRows(QModelIndex(), rowIndex, rowIndex + rows - 1);

    auto firstIterator = mRows.begin() + rowIndex;
    // The "last" argument to erase() is exclusive, so we go one past the last item.
    auto lastIterator = firstIterator + rows;
    mRows.erase(firstIterator, lastIterator);
    mRowCount -= rows;

    endRemoveRows();
    emit rowCountChanged();

    qCDebug(lcTableModel).nospace() << "removed " << rows
        << " items from the model, starting at index " << rowIndex;
}

/*!
    \qmlmethod TableModel::setRow(int rowIndex, object row)

    Changes the row at \a rowIndex in the model with \a row.

    All columns/cells must be present in \c row, and in the correct order.

    \code
        model.setRow(0, {
            checkable: true,
            amount: 1,
            fruitType: "Pear",
            fruitName: "Williams",
            fruitPrice: 1.50,
        })
    \endcode

    If \a rowIndex is equal to \c rowCount(), then a new row is appended to the
    model. Otherwise, \a rowIndex must point to an existing row in the model.

    \sa appendRow(), insertRow(), rowCount
*/
void QQmlTableModel::setRow(int rowIndex, const QVariant &row)
{
    if (!validateNewRow("setRow()", row, rowIndex))
        return;

    if (rowIndex != mRowCount) {
        // Setting an existing row.
        mRows[rowIndex] = row;

        // For now we just assume the whole row changed, as it's simpler.
        const QModelIndex topLeftModelIndex(createIndex(rowIndex, 0));
        const QModelIndex bottomRightModelIndex(createIndex(rowIndex, mColumnCount - 1));
        emit dataChanged(topLeftModelIndex, bottomRightModelIndex);
    } else {
        // Appending a row.
        doInsert(rowIndex, row);
    }
}

QQmlListProperty<QQmlTableModelColumn> QQmlTableModel::columns()
{
    return QQmlListProperty<QQmlTableModelColumn>(this, nullptr,
        &QQmlTableModel::columns_append,
        &QQmlTableModel::columns_count,
        &QQmlTableModel::columns_at,
        &QQmlTableModel::columns_clear);
}

void QQmlTableModel::columns_append(QQmlListProperty<QQmlTableModelColumn> *property,
    QQmlTableModelColumn *value)
{
    QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object);
    QQmlTableModelColumn *column = qobject_cast<QQmlTableModelColumn*>(value);
    if (column)
        model->mColumns.append(column);
}

int QQmlTableModel::columns_count(QQmlListProperty<QQmlTableModelColumn> *property)
{
    const QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object);
    return model->mColumns.count();
}

QQmlTableModelColumn *QQmlTableModel::columns_at(QQmlListProperty<QQmlTableModelColumn> *property, int index)
{
    const QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object);
    return model->mColumns.at(index);
}

void QQmlTableModel::columns_clear(QQmlListProperty<QQmlTableModelColumn> *property)
{
    QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object);
    return model->mColumns.clear();
}

/*!
    \qmlmethod QModelIndex TableModel::index(int row, int column)

    Returns a \l QModelIndex object referencing the given \a row and \a column,
    which can be passed to the data() function to get the data from that cell,
    or to setData() to edit the contents of that cell.

    \code
    import QtQml 2.14
    import Qt.labs.qmlmodels 1.0

    TableModel {
        id: model

        TableModelColumn { display: "fruitType" }
        TableModelColumn { display: "fruitPrice" }

        rows: [
            { fruitType: "Apple", fruitPrice: 1.50 },
            { fruitType: "Orange", fruitPrice: 2.50 }
        ]

        Component.onCompleted: {
            for (var r = 0; r < model.rowCount; ++r) {
                console.log("An " + model.data(model.index(r, 0)).display +
                            " costs " + model.data(model.index(r, 1)).display.toFixed(2))
            }
        }
    }
    \endcode

    \sa {QModelIndex and related Classes in QML}, data()
*/
// Note: we don't document the parent argument, because you never need it, because
// cells in a TableModel don't have parents.  But it is there because this function is an override.
QModelIndex QQmlTableModel::index(int row, int column, const QModelIndex &parent) const
{
    return row >= 0 && row < rowCount() && column >= 0 && column < columnCount() && !parent.isValid()
        ? createIndex(row, column)
        : QModelIndex();
}

/*!
    \qmlproperty int TableModel::rowCount
    \readonly

    This read-only property holds the number of rows in the model.

    This value changes whenever rows are added or removed from the model.
*/
int QQmlTableModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return mRowCount;
}

/*!
    \qmlproperty int TableModel::columnCount
    \readonly

    This read-only property holds the number of columns in the model.

    The number of columns is fixed for the lifetime of the model
    after the \l rows property is set or \l appendRow() is called for the first
    time.
*/
int QQmlTableModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return mColumnCount;
}

/*!
    \qmlmethod variant TableModel::data(QModelIndex index, string role)

    Returns the data from the table cell at the given \a index belonging to the
    given \a role.

    \sa index()
*/
QVariant QQmlTableModel::data(const QModelIndex &index, const QString &role) const
{
    const int iRole = mRoleNames.key(role.toUtf8(), -1);
    if (iRole >= 0)
        return data(index, iRole);
    return QVariant();
}

QVariant QQmlTableModel::data(const QModelIndex &index, int role) const
{
    const int row = index.row();
    if (row < 0 || row >= rowCount())
        return QVariant();

    const int column = index.column();
    if (column < 0 || column >= columnCount())
        return QVariant();

    const ColumnMetadata columnMetadata = mColumnMetadata.at(index.column());
    const QString roleName = QString::fromUtf8(mRoleNames.value(role));
    if (!columnMetadata.roles.contains(roleName)) {
        qmlWarning(this) << "setData(): no role named " << roleName
            << " at column index " << column << ". The available roles for that column are: "
            << columnMetadata.roles.keys();
        return QVariant();
    }

    const ColumnRoleMetadata roleData = columnMetadata.roles.value(roleName);
    if (roleData.isStringRole) {
        // We know the data structure, so we can get the data for the user.
        const QVariantMap rowData = mRows.at(row).toMap();
        const QString propertyName = columnMetadata.roles.value(roleName).name;
        const QVariant value = rowData.value(propertyName);
        return value;
    }

    // We don't know the data structure, so the user has to modify their data themselves.
    // First, find the getter for this column and role.
    QJSValue getter = mColumns.at(column)->getterAtRole(roleName);

    // Then, call it and return what it returned.
    const auto args = QJSValueList() << qmlEngine(this)->toScriptValue(index);
    return getter.call(args).toVariant();
}

/*!
    \qmlmethod bool TableModel::setData(QModelIndex index, string role, variant value)

    Inserts or updates the data field named by \a role in the table cell at the
    given \a index with \a value. Returns true if sucessful, false if not.

    \sa index()
*/
bool QQmlTableModel::setData(const QModelIndex &index, const QString &role, const QVariant &value)
{
    const int intRole = mRoleNames.key(role.toUtf8(), -1);
    if (intRole >= 0)
        return setData(index, value, intRole);
    return false;
}

bool QQmlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    const int row = index.row();
    if (row < 0 || row >= rowCount())
        return false;

    const int column = index.column();
    if (column < 0 || column >= columnCount())
        return false;

    const QString roleName = QString::fromUtf8(mRoleNames.value(role));

    qCDebug(lcTableModel).nospace() << "setData() called with index "
        << index << ", value " << value << " and role " << roleName;

    // Verify that the role exists for this column.
    const ColumnMetadata columnMetadata = mColumnMetadata.at(index.column());
    if (!columnMetadata.roles.contains(roleName)) {
        qmlWarning(this) << "setData(): no role named \"" << roleName
            << "\" at column index " << column << ". The available roles for that column are: "
            << columnMetadata.roles.keys();
        return false;
    }

    // Verify that the type of the value is what we expect.
    // If the value set is not of the expected type, we can try to convert it automatically.
    const ColumnRoleMetadata roleData = columnMetadata.roles.value(roleName);
    QVariant effectiveValue = value;
    if (value.type() != roleData.type) {
        if (!value.canConvert(int(roleData.type))) {
            qmlWarning(this).nospace() << "setData(): the value " << value
                << " set at row " << row << " column " << column << " with role " << roleName
                << " cannot be converted to " << roleData.typeName;
            return false;
        }

        if (!effectiveValue.convert(int(roleData.type))) {
            qmlWarning(this).nospace() << "setData(): failed converting value " << value
                << " set at row " << row << " column " << column << " with role " << roleName
                << " to " << roleData.typeName;
            return false;
        }
    }

    if (roleData.isStringRole) {
        // We know the data structure, so we can set it for the user.
        QVariantMap modifiedRow = mRows.at(row).toMap();
        modifiedRow[roleData.name] = value;

        mRows[row] = modifiedRow;
    } else {
        // We don't know the data structure, so the user has to modify their data themselves.
        auto engine = qmlEngine(this);
        auto args = QJSValueList()
            // arg 0: modelIndex.
            << engine->toScriptValue(index)
            // arg 1: cellData.
            << engine->toScriptValue(value);
        // Do the actual setting.
        QJSValue setter = mColumns.at(column)->setterAtRole(roleName);
        setter.call(args);

        /*
            The chain of events so far:

            - User did e.g.: model.edit = textInput.text
              - setData() is called
                - setData() calls the setter
                  (remember that we need to emit the dataChanged() signal,
                   which is why the user can't just set the data directly in the delegate)

            Now the user's setter function has modified *their* copy of the
            data, but *our* copy of the data is old. Imagine the getters and setters looked like this:

            display: function(modelIndex) { return rows[modelIndex.row][1].amount }
            setDisplay: function(modelIndex, cellData) { rows[modelIndex.row][1].amount = cellData }

            We don't know the structure of the user's data, so we can't just do
            what we do above for the isStringRole case:

            modifiedRow[column][roleName] = value

            This means that, besides getting the implicit row count when rows is initially set,
            our copy of the data is unused when it comes to complex columns.

            Another point to note is that we can't pass rowData in to the getter as a convenience,
            because we would be passing in *our* copy of the row, which is not up-to-date.
            Since the user already has access to the data, it's not a big deal for them to do:

            display: function(modelIndex) { return rows[modelIndex.row][1].amount }

            instead of:

            display: function(modelIndex, rowData) { return rowData[1].amount }
        */
    }

    QVector<int> rolesChanged;
    rolesChanged.append(role);
    emit dataChanged(index, index, rolesChanged);

    return true;
}

QHash<int, QByteArray> QQmlTableModel::roleNames() const
{
    return mRoleNames;
}

QQmlTableModel::ColumnRoleMetadata::ColumnRoleMetadata()
{
}

QQmlTableModel::ColumnRoleMetadata::ColumnRoleMetadata(
    bool isStringRole, const QString &name, QVariant::Type type, const QString &typeName) :
    isStringRole(isStringRole),
    name(name),
    type(type),
    typeName(typeName)
{
}

bool QQmlTableModel::ColumnRoleMetadata::isValid() const
{
    return !name.isEmpty();
}

bool QQmlTableModel::validateRowType(const char *functionName, const QVariant &row) const
{
    if (!row.canConvert<QJSValue>()) {
        qmlWarning(this) << functionName << ": expected \"row\" argument to be a QJSValue,"
            << " but got " << row.typeName() << " instead:\n" << row;
        return false;
    }

    const QJSValue rowAsJSValue = row.value<QJSValue>();
    if (!rowAsJSValue.isObject() && !rowAsJSValue.isArray()) {
        qmlWarning(this) << functionName << ": expected \"row\" argument "
            << "to be an object or array, but got:\n" << rowAsJSValue.toString();
        return false;
    }

    return true;
}

bool QQmlTableModel::validateNewRow(const char *functionName, const QVariant &row,
    int rowIndex, NewRowOperationFlag operation) const
{
    if (mColumnMetadata.isEmpty()) {
        // There is no column metadata, so we have nothing to validate the row against.
        // Rows have to be added before we can gather metadata from them, so just this
        // once we'll return true to allow the rows to be added.
        return true;
    }

    // Don't require each row to be a QJSValue when setting all rows,
    // as they won't be; they'll be QVariantMap.
    if (operation != SetRowsOperation && !validateRowType(functionName, row))
        return false;

    if (operation == OtherOperation) {
        // Inserting/setting.
        if (rowIndex < 0) {
            qmlWarning(this) << functionName << ": \"rowIndex\" cannot be negative";
            return false;
        }

        if (rowIndex > mRowCount) {
            qmlWarning(this) << functionName << ": \"rowIndex\" " << rowIndex
                << " is greater than rowCount() of " << mRowCount;
            return false;
        }
    }

    const QVariant rowAsVariant = operation == SetRowsOperation
        ? row : row.value<QJSValue>().toVariant();
    if (rowAsVariant.type() != QVariant::Map) {
        qmlWarning(this) << functionName << ": row manipulation functions "
            << "do not support complex rows (row index: " << rowIndex << ")";
        return false;
    }

    const QVariantMap rowAsMap = rowAsVariant.toMap();
    const int columnCount = rowAsMap.size();
    if (columnCount < mColumnCount) {
        qmlWarning(this) << functionName << ": expected " << mColumnCount
            << " columns, but only got " << columnCount;
        return false;
    }

    // We can't validate complex structures, but we can make sure that
    // each simple string-based role in each column is correct.
    for (int columnIndex = 0; columnIndex < mColumns.size(); ++columnIndex) {
        QQmlTableModelColumn *column = mColumns.at(columnIndex);
        const QHash<QString, QJSValue> getters = column->getters();
        const auto roleNames = getters.keys();
        const ColumnMetadata columnMetadata = mColumnMetadata.at(columnIndex);
        for (const QString &roleName : roleNames) {
            const ColumnRoleMetadata roleData = columnMetadata.roles.value(roleName);
            if (!roleData.isStringRole)
                continue;

            if (!rowAsMap.contains(roleData.name)) {
                qmlWarning(this).quote() << functionName << ": expected a property named "
                    << roleData.name << " in row at index " << rowIndex << ", but couldn't find one";
                return false;
            }

            const QVariant rolePropertyValue = rowAsMap.value(roleData.name);
            if (rolePropertyValue.type() != roleData.type) {
                qmlWarning(this).quote() << functionName << ": expected the property named "
                    << roleData.name << " to be of type " << roleData.typeName
                    << ", but got " << QString::fromLatin1(rolePropertyValue.typeName()) << " instead";
                return false;
            }
        }
    }

    return true;
}

bool QQmlTableModel::validateRowIndex(const char *functionName, const char *argumentName, int rowIndex) const
{
    if (rowIndex < 0) {
        qmlWarning(this) << functionName << ": \"" << argumentName << "\" cannot be negative";
        return false;
    }

    if (rowIndex >= mRowCount) {
        qmlWarning(this) << functionName << ": \"" << argumentName
            << "\" " << rowIndex << " is greater than or equal to rowCount() of " << mRowCount;
        return false;
    }

    return true;
}

QT_END_NAMESPACE
