fix: Handle source model with no roles better

They are now handled in setSourceModel instead of resetInternalData
Fixes #46
This commit is contained in:
Grecko 2018-03-22 23:39:53 +01:00
parent 9c3e57c02e
commit 8499099464
2 changed files with 36 additions and 23 deletions

View File

@ -198,10 +198,10 @@ QQmlListProperty<Sorter> QQmlSortFilterProxyModel::sorters()
QQmlListProperty<ProxyRole> QQmlSortFilterProxyModel::proxyRoles()
{
return QQmlListProperty<ProxyRole>(this, &m_proxyRoles,
&QQmlSortFilterProxyModel::append_proxyRole,
&QQmlSortFilterProxyModel::count_proxyRole,
&QQmlSortFilterProxyModel::at_proxyRole,
&QQmlSortFilterProxyModel::clear_proxyRoles);
&QQmlSortFilterProxyModel::append_proxyRole,
&QQmlSortFilterProxyModel::count_proxyRole,
&QQmlSortFilterProxyModel::at_proxyRole,
&QQmlSortFilterProxyModel::clear_proxyRoles);
}
void QQmlSortFilterProxyModel::classBegin()
@ -245,7 +245,7 @@ QVariant QQmlSortFilterProxyModel::data(const QModelIndex &index, int role) cons
QHash<int, QByteArray> QQmlSortFilterProxyModel::roleNames() const
{
return m_roleNames;
return m_roleNames.isEmpty() && sourceModel() ? sourceModel()->roleNames() : m_roleNames;
}
/*!
@ -257,7 +257,7 @@ QHash<int, QByteArray> QQmlSortFilterProxyModel::roleNames() const
int QQmlSortFilterProxyModel::roleForName(const QString& roleName) const
{
return roleNames().key(roleName.toUtf8(), -1);
return m_roleNames.key(roleName.toUtf8(), -1);
}
/*!
@ -373,24 +373,16 @@ bool QQmlSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QM
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);
}
m_roleNames = QSortFilterProxyModel::roleNames();
m_proxyRoleMap.clear();
m_proxyRoleNumbers.clear();
updateRoleNames();
}
auto roles = m_roleNames.keys();
auto maxIt = std::max_element(roles.cbegin(), roles.cend());
int maxRole = maxIt != roles.cend() ? *maxIt : -1;
for (auto proxyRole : m_proxyRoles) {
++maxRole;
m_roleNames[maxRole] = proxyRole->name().toUtf8();
m_proxyRoleMap[maxRole] = proxyRole;
m_proxyRoleNumbers.append(maxRole);
void QQmlSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
if (sourceModel && sourceModel->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);
}
QSortFilterProxyModel::setSourceModel(sourceModel);
}
void QQmlSortFilterProxyModel::invalidateFilter()
@ -405,6 +397,25 @@ void QQmlSortFilterProxyModel::invalidate()
QSortFilterProxyModel::invalidate();
}
void QQmlSortFilterProxyModel::updateRoleNames()
{
if (!sourceModel())
return;
m_roleNames = sourceModel()->roleNames();
m_proxyRoleMap.clear();
m_proxyRoleNumbers.clear();
auto roles = m_roleNames.keys();
auto maxIt = std::max_element(roles.cbegin(), roles.cend());
int maxRole = maxIt != roles.cend() ? *maxIt : -1;
for (auto proxyRole : m_proxyRoles) {
++maxRole;
m_roleNames[maxRole] = proxyRole->name().toUtf8();
m_proxyRoleMap[maxRole] = proxyRole;
m_proxyRoleNumbers.append(maxRole);
}
}
void QQmlSortFilterProxyModel::updateFilterRole()
{
QList<int> filterRoles = roleNames().keys(m_filterRoleName.toUtf8());
@ -433,7 +444,6 @@ void QQmlSortFilterProxyModel::updateRoles()
void QQmlSortFilterProxyModel::initRoles()
{
disconnect(sourceModel(), &QAbstractItemModel::rowsInserted, this, &QQmlSortFilterProxyModel::initRoles);
disconnect(this, &QAbstractItemModel::rowsAboutToBeInserted, this , &QQmlSortFilterProxyModel::initRoles);
resetInternalData();
updateRoles();
}

View File

@ -85,6 +85,8 @@ public:
Q_INVOKABLE QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override;
Q_INVOKABLE int mapFromSource(int sourceRow) const;
void setSourceModel(QAbstractItemModel *sourceModel) override;
Q_SIGNALS:
void countChanged();
@ -106,6 +108,7 @@ protected Q_SLOTS:
private Q_SLOTS:
void invalidateFilter();
void invalidate();
void updateRoleNames();
void updateFilterRole();
void updateSortRole();
void updateRoles();