QTableView不更新数据

QTableView does not update the data

我正在使用 QTableView 查看 sql 数据库中的一些数据。 结构如下:

  1. QSqlQueryModel
  2. QSortFilterProxyModel 的子类,用于通过搜索框过滤数据
  3. QTableView 及其模型是代理模型。

有时当我搜索并调用 FilterAcceptsRow 时,视图不会加载数据,令人惊讶的是当我调整 window 的大小或单击 header 对其进行排序时,数据得到已加载!

bool ProxyModel::filterAcceptsRow(int source_row,
                                  const QModelIndex &source_parent) const
{
    QModelIndex indName = sourceModel()->index(source_row,
                                               7, source_parent);
    QModelIndex indNumber= sourceModel()->index(source_row,
                                               6, source_parent);
    QModelIndex indAgency = sourceModel()->index(source_row,
                                               0, source_parent);

    QModelIndex indStartDate = sourceModel()->index(source_row,2,source_parent);
    QModelIndex indEndDate = sourceModel()->index(source_row,1,source_parent);
    if (searchBy == 0) // search by name
    {
        if(sourceModel()->data(indName).toString().contains(name_))
            return true;
        else
            return false;
    }
    else if( searchBy == 1)  // search by number
    {
        if(sourceModel()->data(indNumber).toString().toLower().contains(number_.toLower()))
            return true;
        else
            return false;
    }
    else if (searchBy == 2) // search by agency
    {
        return agencyList.indexOf(sourceModel()->data(indAgency).toString()) == agency_ ;
    }

    else if (searchBy == 3) // search By date
    {
        if (sourceModel()->data(indStartDate).toDate() >= start_ &&
               sourceModel()->data(indEndDate).toDate() <= end_)
        return true;
    }

    return false;
}

有什么办法可以让它正常工作吗?

这是我项目中的一个工作片段

#include "qqmlsortfilterproxymodel.h"
#include <QtQml>
#include <algorithm>
#include "filter.h"
#include "sorter.h"

QQmlSortFilterProxyModel::QQmlSortFilterProxyModel(QObject *parent) :
    QSortFilterProxyModel(parent)
{
    connect(this, &QAbstractProxyModel::sourceModelChanged, this, &QQmlSortFilterProxyModel::updateRoles);
    connect(this, &QAbstractItemModel::modelReset, this, &QQmlSortFilterProxyModel::updateRoles);
    connect(this, &QAbstractItemModel::rowsInserted, this, &QQmlSortFilterProxyModel::countChanged);
    connect(this, &QAbstractItemModel::rowsRemoved, this, &QQmlSortFilterProxyModel::countChanged);
    connect(this, &QAbstractItemModel::modelReset, this, &QQmlSortFilterProxyModel::countChanged);
    connect(this, &QAbstractItemModel::layoutChanged, this, &QQmlSortFilterProxyModel::countChanged);
    setDynamicSortFilter(true);
}

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

const QString& QQmlSortFilterProxyModel::filterRoleName() const
{
    return m_filterRoleName;
}

void QQmlSortFilterProxyModel::setFilterRoleName(const QString& filterRoleName)
{
    if (m_filterRoleName == filterRoleName)
        return;

    m_filterRoleName = filterRoleName;
    updateFilterRole();
    Q_EMIT filterRoleNameChanged();
}

QString QQmlSortFilterProxyModel::filterPattern() const
{
    return filterRegExp().pattern();
}

void QQmlSortFilterProxyModel::setFilterPattern(const QString& filterPattern)
{
    QRegExp regExp = filterRegExp();
    if (regExp.pattern() == filterPattern)
        return;

    regExp.setPattern(filterPattern);
    QSortFilterProxyModel::setFilterRegExp(regExp);
    Q_EMIT filterPatternChanged();
}

QQmlSortFilterProxyModel::PatternSyntax QQmlSortFilterProxyModel::filterPatternSyntax() const
{
    return static_cast<PatternSyntax>(filterRegExp().patternSyntax());
}

void QQmlSortFilterProxyModel::setFilterPatternSyntax(QQmlSortFilterProxyModel::PatternSyntax patternSyntax)
{
    QRegExp regExp = filterRegExp();
    QRegExp::PatternSyntax patternSyntaxTmp = static_cast<QRegExp::PatternSyntax>(patternSyntax);
    if (regExp.patternSyntax() == patternSyntaxTmp)
        return;

    regExp.setPatternSyntax(patternSyntaxTmp);
    QSortFilterProxyModel::setFilterRegExp(regExp);
    Q_EMIT filterPatternSyntaxChanged();
}

const QVariant& QQmlSortFilterProxyModel::filterValue() const
{
    return m_filterValue;
}

void QQmlSortFilterProxyModel::setFilterValue(const QVariant& filterValue)
{
    if (m_filterValue == filterValue)
        return;

    m_filterValue = filterValue;
    invalidateFilter();
    Q_EMIT filterValueChanged();
}

const QString& QQmlSortFilterProxyModel::sortRoleName() const
{
    return m_sortRoleName;
}

void QQmlSortFilterProxyModel::setSortRoleName(const QString& sortRoleName)
{
    if (m_sortRoleName == sortRoleName)
        return;

    m_sortRoleName = sortRoleName;
    updateSortRole();
    Q_EMIT sortRoleNameChanged();
}

bool QQmlSortFilterProxyModel::ascendingSortOrder() const
{
    return m_ascendingSortOrder;
}

void QQmlSortFilterProxyModel::setAscendingSortOrder(bool ascendingSortOrder)
{
    if (m_ascendingSortOrder == ascendingSortOrder)
        return;

    m_ascendingSortOrder = ascendingSortOrder;
    Q_EMIT ascendingSortOrderChanged();
    invalidate();
}

QQmlListProperty<Filter> QQmlSortFilterProxyModel::filters()
{
    return QQmlListProperty<Filter>(this, &m_filters,
                                    &QQmlSortFilterProxyModel::append_filter,
                                    &QQmlSortFilterProxyModel::count_filter,
                                    &QQmlSortFilterProxyModel::at_filter,
                                    &QQmlSortFilterProxyModel::clear_filters);
}

QQmlListProperty<Sorter> QQmlSortFilterProxyModel::sorters()
{
    return QQmlListProperty<Sorter>(this, &m_sorters,
                                    &QQmlSortFilterProxyModel::append_sorter,
                                    &QQmlSortFilterProxyModel::count_sorter,
                                    &QQmlSortFilterProxyModel::at_sorter,
                                    &QQmlSortFilterProxyModel::clear_sorters);
}

void QQmlSortFilterProxyModel::classBegin()
{

}

void QQmlSortFilterProxyModel::componentComplete()
{
    m_completed = true;
    for (const auto& filter : m_filters)
        filter->proxyModelCompleted();
    invalidate();
    sort(0);
}
QVariant QQmlSortFilterProxyModel::sourceData(const QModelIndex& sourceIndex, const QString& roleName) const
{
    int role = sourceModel()->roleNames().key(roleName.toUtf8());
    return sourceData(sourceIndex, role);
}

QVariant QQmlSortFilterProxyModel::sourceData(const QModelIndex &sourceIndex, int role) const
{
    return sourceModel()->data(sourceIndex, role);
}

int QQmlSortFilterProxyModel::roleForName(const QString& roleName) const
{
    return roleNames().key(roleName.toUtf8(), -1);
}

QVariantMap QQmlSortFilterProxyModel::get(int row) const
{
    QVariantMap map;
    QModelIndex modelIndex = index(row, 0);
    QHash<int, QByteArray> roles = roleNames();
    for (QHash<int, QByteArray>::const_iterator it = roles.begin(); it != roles.end(); ++it)
       map.insert(it.value(), data(modelIndex, it.key()));

    return map;
}

QVariant QQmlSortFilterProxyModel::get(int row, const QString& roleName) const
{
    return data(index(row, 0), roleForName(roleName));
}

QModelIndex QQmlSortFilterProxyModel::mapToSource(const QModelIndex& proxyIndex) const
{
    return QSortFilterProxyModel::mapToSource(proxyIndex);
}

int QQmlSortFilterProxyModel::mapToSource(int proxyRow) const
{
    QModelIndex proxyIndex = index(proxyRow, 0);
    QModelIndex sourceIndex = mapToSource(proxyIndex);
    return sourceIndex.isValid() ? sourceIndex.row() : -1;
}

QModelIndex QQmlSortFilterProxyModel::mapFromSource(const QModelIndex& sourceIndex) const
{
    return QSortFilterProxyModel::mapFromSource(sourceIndex);
}

int QQmlSortFilterProxyModel::mapFromSource(int sourceRow) const
{
    QModelIndex proxyIndex;
    if (QAbstractItemModel* source = sourceModel()) {
        QModelIndex sourceIndex = source->index(sourceRow, 0);
        proxyIndex = mapFromSource(sourceIndex);
    }
    return proxyIndex.isValid() ? proxyIndex.row() : -1;
}

bool QQmlSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
{
    if (!m_completed)
        return true;
    QModelIndex sourceIndex = sourceModel()->index(source_row, 0, source_parent);
    bool valueAccepted = !m_filterValue.isValid() || ( m_filterValue == sourceModel()->data(sourceIndex, filterRole()) );
    bool baseAcceptsRow = valueAccepted && QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
    baseAcceptsRow = baseAcceptsRow && std::all_of(m_filters.begin(), m_filters.end(),
        [=, &source_parent] (Filter* filter) {
            return filter->filterAcceptsRow(sourceIndex);
        }
    );
    return baseAcceptsRow;
}

bool QQmlSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const
{
    if (m_completed) {
        if (!m_sortRoleName.isEmpty()) {
            if (QSortFilterProxyModel::lessThan(source_left, source_right))
                return m_ascendingSortOrder;
            if (QSortFilterProxyModel::lessThan(source_right, source_left))
                return !m_ascendingSortOrder;
        }
        for(auto sorter : m_sorters) {
            if (sorter->enabled()) {
                int comparison = sorter->compareRows(source_left, source_right);
                if (comparison != 0)
                    return comparison < 0;
            }
        }
    }
    return source_left.row() < source_right.row();
}

void QQmlSortFilterProxyModel::resetInternalData()
{
    QSortFilterProxyModel::resetInternalData();
    if (sourceModel() && QSortFilterProxyModel::roleNames().isEmpty()) { // workaround for when a model has no roles and roles are added when the model is populated (ListModel)
        // QTBUG-57971
        connect(sourceModel(), &QAbstractItemModel::rowsInserted, this, &QQmlSortFilterProxyModel::initRoles);
        connect(this, &QAbstractItemModel::rowsAboutToBeInserted, this, &QQmlSortFilterProxyModel::initRoles);
    }
}

void QQmlSortFilterProxyModel::invalidateFilter()
{
    if (m_completed)
        QSortFilterProxyModel::invalidateFilter();
}

void QQmlSortFilterProxyModel::invalidate()
{
    if (m_completed)
        QSortFilterProxyModel::invalidate();
}

void QQmlSortFilterProxyModel::updateFilterRole()
{
    QList<int> filterRoles = roleNames().keys(m_filterRoleName.toUtf8());
    if (!filterRoles.empty())
    {
        setFilterRole(filterRoles.first());
    }
}

void QQmlSortFilterProxyModel::updateSortRole()
{
    QList<int> sortRoles = roleNames().keys(m_sortRoleName.toUtf8());
    if (!sortRoles.empty())
    {
        setSortRole(sortRoles.first());
        invalidate();
    }
}

void QQmlSortFilterProxyModel::updateRoles()
{
    updateFilterRole();
    updateSortRole();
}

void QQmlSortFilterProxyModel::initRoles()
{
    disconnect(sourceModel(), &QAbstractItemModel::rowsInserted, this, &QQmlSortFilterProxyModel::initRoles);
    disconnect(this, &QAbstractItemModel::rowsAboutToBeInserted, this , &QQmlSortFilterProxyModel::initRoles);
    resetInternalData();
    updateRoles();
}

QVariantMap QQmlSortFilterProxyModel::modelDataMap(const QModelIndex& modelIndex) const
{
    QVariantMap map;
    QHash<int, QByteArray> roles = roleNames();
    for (QHash<int, QByteArray>::const_iterator it = roles.begin(); it != roles.end(); ++it)
        map.insert(it.value(), sourceModel()->data(modelIndex, it.key()));
    return map;
}

void QQmlSortFilterProxyModel::append_filter(QQmlListProperty<Filter>* list, Filter* filter)
{
    if (!filter)
        return;

    QQmlSortFilterProxyModel* that = static_cast<QQmlSortFilterProxyModel*>(list->object);
    that->m_filters.append(filter);
    connect(filter, &Filter::invalidate, that, &QQmlSortFilterProxyModel::invalidateFilter);
    filter->m_proxyModel = that;
    that->invalidateFilter();
}

int QQmlSortFilterProxyModel::count_filter(QQmlListProperty<Filter>* list)
{
    QList<Filter*>* filters = static_cast<QList<Filter*>*>(list->data);
    return filters->count();
}

Filter* QQmlSortFilterProxyModel::at_filter(QQmlListProperty<Filter>* list, int index)
{
    QList<Filter*>* filters = static_cast<QList<Filter*>*>(list->data);
    return filters->at(index);
}

void QQmlSortFilterProxyModel::clear_filters(QQmlListProperty<Filter> *list)
{
    QQmlSortFilterProxyModel* that = static_cast<QQmlSortFilterProxyModel*>(list->object);
    that->m_filters.clear();
    that->invalidateFilter();
}

void QQmlSortFilterProxyModel::append_sorter(QQmlListProperty<Sorter>* list, Sorter* sorter)
{
    if (!sorter)
        return;

    auto that = static_cast<QQmlSortFilterProxyModel*>(list->object);
    that->m_sorters.append(sorter);
    connect(sorter, &Sorter::invalidate, that, &QQmlSortFilterProxyModel::invalidate);
    sorter->m_proxyModel = that;
    that->invalidate();
}

int QQmlSortFilterProxyModel::count_sorter(QQmlListProperty<Sorter>* list)
{
    auto sorters = static_cast<QList<Sorter*>*>(list->data);
    return sorters->count();
}

Sorter* QQmlSortFilterProxyModel::at_sorter(QQmlListProperty<Sorter>* list, int index)
{
    auto sorters = static_cast<QList<Sorter*>*>(list->data);
    return sorters->at(index);
}

void QQmlSortFilterProxyModel::clear_sorters(QQmlListProperty<Sorter>* list)
{
    auto that = static_cast<QQmlSortFilterProxyModel*>(list->object);
    that->m_sorters.clear();
    that->invalidate();
}

int QQmlSortFilterProxyModel::getRowCount() const
{
   return rowCount();
}

void registerQQmlSortFilterProxyModelTypes() {
    qmlRegisterType<QQmlSortFilterProxyModel>("SortFilterProxyModel", 0, 2, "SortFilterProxyModel");
}

Q_COREAPP_STARTUP_FUNCTION(registerQQmlSortFilterProxyModelTypes)

我找到了该问题的修复方法,事实证明,QSortFilterProxyModel 不会加载所有数据,直到您向下滚动 QTableView,然后它才开始加载其余数据。 如果有大量数据,这可能是一件好事,所以默认情况下它是打开的。

我通过使用

让它按照我需要的方式工作
bool QAbstractItemModel::canFetchMore(const QModelIndex &parent) const

void QAbstractItemModel::fetchMore(const QModelIndex &parent)

每次调用后 invalidateFilter();

我打电话给他们来获取所有数据

while (canFetchMore(sourceModel()->index(rowCount()-1,0)))
{
    fetchMore(sourceModel()->index(rowCount()-1,0));
}