Как исправить баг с цветовой индикацией строк QML TableView

У меня есть TableView и модель C ++, я также использую прокси-модель. Я хочу выделить строки разными цветами в зависимости от содержимого. Это хорошо работает, пока я не попытаюсь отсортировать модель. После сортировки строки остаются окрашенными как по старому индексу, так и по новому. Но после того, как делегат строки со старым индексом исчезает из поля зрения, он перестает окрашиваться. Мне приходится пролистывать таблицу, чтобы скрыть делегатов и изменить их цвет. Может нужно обновить вид? Но я не нашел для этого никаких способов. Как исправить эту ошибку? Вот ссылка на мой репозиторий git с минимальным воспроизводимым примером. Я вырезал часть кода из основного проекта, удалил всё лишнее и убедился что ошибка воспроизводится. github.com/Felinor/TableViewQML

Как воспроизвести баг: дважды щелкните заголовок для сортировки (вы увидите, что сортировка завершена, но старые строки все еще окрашены), затем прокрутите таблицу вниз и вы найдете две цветные отсортированные строки, затем снова прокрутите вверх и вы увидите, что две строки по старому индексу ошибочно окрашенные приобрели правильный окрас. Я действительно не знаю где искать причину бага.

Вот функция которую я использую для окрашивания строк, но я не думаю что проблема в ней.

function colorNotify() {
        var key = proxyModel.get(styleData.row).dataNotification
        if (key === "parameter 1")
            return gradientAttention
        else if (key === "parameter 10")
            return gradientWarning
        else if (delegateRow.hovered)
            return gradientCurrentRow

        return gradientNormal
    }

Вот прокси модель, может быть баг кроется в ней.

#ifndef PROXYMODEL_H
#define PROXYMODEL_H

#include <QtCore/qsortfilterproxymodel.h>
#include <QtQml/qqmlparserstatus.h>
#include <QtQml/qjsvalue.h>
#include <QtQml>
#include "model.h"

class SortFilterProxyModel : public QSortFilterProxyModel, public QQmlParserStatus
{
    Q_OBJECT
    Q_INTERFACES(QQmlParserStatus)

    Q_PROPERTY(int count READ count NOTIFY countChanged)
    Q_PROPERTY(QObject *source READ source WRITE setSource)

    Q_PROPERTY(QByteArray sortRole READ sortRole WRITE setSortRole)
    Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder)

    Q_PROPERTY(QByteArray filterRole READ filterRole WRITE setFilterRole)
    Q_PROPERTY(QString filterString READ filterString WRITE setFilterString)
    Q_PROPERTY(FilterSyntax filterSyntax READ filterSyntax WRITE setFilterSyntax)

    Q_ENUMS(FilterSyntax)

public:
    explicit SortFilterProxyModel(QObject *parent = 0);

    QObject *source() const;
    void setSource(QObject *source);

    QByteArray sortRole() const;
    void setSortRole(const QByteArray &role);

    void setSortOrder(Qt::SortOrder order);

    QByteArray filterRole() const;
    void setFilterRole(const QByteArray &role);

    QString filterString() const;
    void setFilterString(const QString &filter);

    enum FilterSyntax {
        RegExp,
        Wildcard,
        FixedString
    };

    FilterSyntax filterSyntax() const;
    void setFilterSyntax(FilterSyntax syntax);

    int count() const;
    Q_INVOKABLE QJSValue get(int index) const;
    Q_INVOKABLE void reserve(const int &currentIndex);
    Q_INVOKABLE QModelIndex getIndex(const int &currentIndex);

    void classBegin();
    void componentComplete();

signals:
    void countChanged();

protected:
    int roleKey(const QByteArray &role) const;
    QHash<int, QByteArray> roleNames() const;
    bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;

private:
    bool m_complete;
    QByteArray m_sortRole;
    QByteArray m_filterRole;
    QMap<QPersistentModelIndex, QPersistentModelIndex> mapping;
};
#endif // PROXYMODEL_H
#include "proxyModel.h"

SortFilterProxyModel::SortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent), m_complete(false)
{
    connect(this, &QSortFilterProxyModel::rowsInserted, this, &SortFilterProxyModel::countChanged);
    connect(this, &QSortFilterProxyModel::rowsRemoved, this, &SortFilterProxyModel::countChanged);
}

int SortFilterProxyModel::count() const
{
    return rowCount();
}

QObject *SortFilterProxyModel::source() const
{
    return sourceModel();
}

void SortFilterProxyModel::setSource(QObject *source)
{
    setSourceModel(qobject_cast<QAbstractItemModel *>(source));
}

QByteArray SortFilterProxyModel::sortRole() const
{
    return m_sortRole;
}

void SortFilterProxyModel::setSortRole(const QByteArray &role)
{
    if (m_sortRole != role) {
        m_sortRole = role;
        if (m_complete)
            QSortFilterProxyModel::setSortRole(roleKey(role));
    }
}

void SortFilterProxyModel::setSortOrder(Qt::SortOrder order)
{
    QSortFilterProxyModel::sort(0, order);
}

QByteArray SortFilterProxyModel::filterRole() const
{
    return m_filterRole;
}

void SortFilterProxyModel::setFilterRole(const QByteArray &role)
{
    if (m_filterRole != role) {
        m_filterRole = role;
        if (m_complete)
            QSortFilterProxyModel::setFilterRole(roleKey(role));
    }
}

QString SortFilterProxyModel::filterString() const
{
    return filterRegExp().pattern();
}

void SortFilterProxyModel::setFilterString(const QString &filter)
{
    setFilterRegExp(QRegExp(filter, filterCaseSensitivity(), static_cast<QRegExp::PatternSyntax>(filterSyntax())));
}

SortFilterProxyModel::FilterSyntax SortFilterProxyModel::filterSyntax() const
{
    return static_cast<FilterSyntax>(filterRegExp().patternSyntax());
}

void SortFilterProxyModel::setFilterSyntax(SortFilterProxyModel::FilterSyntax syntax)
{
    setFilterRegExp(QRegExp(filterString(), filterCaseSensitivity(), static_cast<QRegExp::PatternSyntax>(syntax)));
}

QJSValue SortFilterProxyModel::get(int idx) const
{
    QJSEngine *engine = qmlEngine(this);
    QJSValue value = engine->newObject();
    if (idx >= 0 && idx < count()) {
        QHash<int, QByteArray> roles = roleNames();
        for (auto it = roles.cbegin(), end = roles.cend(); it != end; ++it)
            value.setProperty(QString::fromUtf8(it.value()), data(index(idx, 0), it.key()).toString());
    }
    return value;
}

void SortFilterProxyModel::classBegin()
{
}

void SortFilterProxyModel::componentComplete()
{
    m_complete = true;
    if (!m_sortRole.isEmpty())
        QSortFilterProxyModel::setSortRole(roleKey(m_sortRole));
    if (!m_filterRole.isEmpty())
        QSortFilterProxyModel::setFilterRole(roleKey(m_filterRole));
}

int SortFilterProxyModel::roleKey(const QByteArray &role) const
{
    return roleNames().key(role, -1);
}

QHash<int, QByteArray> SortFilterProxyModel::roleNames() const
{
    if (QAbstractItemModel *source = sourceModel())
        return source->roleNames();
    return QHash<int, QByteArray>();
}

bool SortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    QRegExp rx = filterRegExp();
    if (rx.isEmpty())
        return true;
    QAbstractItemModel *model = sourceModel();
    if (filterRole().isEmpty()) {
        QHash<int, QByteArray> roles = roleNames();
        for (auto it = roles.cbegin(), end = roles.cend(); it != end; ++it) {
            QModelIndex sourceIndex = model->index(sourceRow, 0, sourceParent);
            QString key = model->data(sourceIndex, it.key()).toString();
            if (key.contains(rx))
                return true;
        }
        return false;
    }
    QModelIndex sourceIndex = model->index(sourceRow, 0, sourceParent);
    if (!sourceIndex.isValid())
        return true;
    QString key = model->data(sourceIndex, roleKey(filterRole())).toString();
    return key.contains(rx);
}

void SortFilterProxyModel::reserve(const int &currentIndex)
{
    QModelIndex proxyIndex = index(currentIndex, 0);
    QModelIndex sourceIndex = mapToSource(proxyIndex);

    DataModel *dataModel = dynamic_cast<DataModel*>(sourceModel());
    dataModel->reserve(sourceIndex.row());
}

QModelIndex SortFilterProxyModel::getIndex(const int &currentIndex)
{
    //QModelIndex proxyIndex = index(currentIndex, 0);
    //QModelIndex sourceIndex = mapToSource(proxyIndex);
    //return sourceIndex;

    DataModel *dataModel = dynamic_cast<DataModel*>(sourceModel());
    return dataModel->index(currentIndex);
}

Ответы (0 шт):