Как правильно реализовать проверяемый ListView в QtQuick2?

Исходя из C++, я не знаю, как правильно реализовать проверяемый ListView в QtQuick.

Для тестирования я создал небольшое тестовое приложение.

Модель:

class MyModel : public QAbstractListModel
{
    Q_OBJECT

public:
    MyModel(QObject *parent = Q_NULLPTR) :
        QAbstractListModel(parent)
    {
        for(int i = 0; i < 10; i++)
            m_items.insert(QString("item%0").arg(i), qrand() % 2 == 0 ? Qt::Checked : Qt::Unchecked);
    }

    int rowCount(const QModelIndex& parent) const Q_DECL_OVERRIDE
    {
        return m_items.count();
    }

    QVariant data(const QModelIndex& index, int role) const Q_DECL_OVERRIDE
    {
        if(index.row() >= m_items.count())
            return QVariant();

        auto key = m_items.keys().at(index.row());

        switch(role)
        {
        case Qt::DisplayRole:
            return key;
        case Qt::CheckStateRole:
            return m_items[key];
        }

        return QVariant();
    }

    bool setData(const QModelIndex& index, const QVariant& value, int role) Q_DECL_OVERRIDE
    {
        qDebug() << "setData()" << index.row() << value << role;

        switch(role)
        {
        case Qt::CheckStateRole:
        {
            auto key = m_items.keys().at(index.row());
            m_items[key] = value.value<Qt::CheckState>();
            emit dataChanged(index, index, QVector<int> { Qt::CheckStateRole });
            return true;
        }
        }

        return QAbstractListModel::setData(index, value, role);
    }

    Qt::ItemFlags flags(const QModelIndex& index) const Q_DECL_OVERRIDE
    {
        Qt::ItemFlags f = QAbstractListModel::flags(index);
        if(index.isValid())
            f |= Qt::ItemIsUserCheckable;
        return f;
    }

    QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE
    {
        return QHash<int, QByteArray> {
            { Qt::DisplayRole, QByteArrayLiteral("display") },
            { Qt::CheckStateRole, QByteArrayLiteral("checkState") },
        };
    }

private:
    QMap<QString, Qt::CheckState> m_items;
};

Во время выполнения я создаю виджет QListView и элемент ListView QtQuick2. Оба прикреплены к одной модели.

При проверке / снятии отметки в виджете представление qml обновляется корректно. При установке / снятии отметки в представлении qml вид виджета не изменяется!

Я заметил, что мой setData не вызывается.

Как правильно реализовать проверяемый ListView в QtQuick2?

ListView {
    anchors.fill: parent

    model: __myModel

    delegate: CheckDelegate {
        text: model.display
        checked: model.checkState
    }
}

1 ответ

Решение

Проблема действительно в том, что CheckDelegate не звонит setData автоматически. Вы должны сказать это, чтобы сделать это. Для этого вы можете использовать toggled сигнал:

delegate: CheckDelegate {
    text: model.display
    checked: model.checkState
    onToggled: model.checkState = checked // this will call setData for CheckStateRole
}
Другие вопросы по тегам