From 0471fc0f4685c8e2f821322fd2c56a4beafbd245 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 11 Jul 2018 16:19:31 +0200 Subject: Fix assert when filtering examples / tutorials The examples are put throw two proxy models. The first one implements the sorting and filtering, the second one transforms the list into a grid. The grid proxy model was based on QIdentityProxyModel, which is wrong because that explicitly states that it should be used when the structure of the model stays the same. Even QAbstractProxyModel works under the assumption that all items in the proxy model correspond to an item in the source model, which is not true for a N*M grid. Just implement the proxy model "by hand", making sure that all items that cannot be mapped to the source are handles correctly as "empty" items. Task-number: QTCREATORBUG-20641 Change-Id: Id08b77bb7157b893b9d0d73dc006db98d90032b7 Reviewed-by: hjk --- .../qtsupport/gettingstartedwelcomepage.cpp | 71 ++++++++++++++++++++-- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp index e0698965e2..4407de9a06 100644 --- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp +++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp @@ -293,12 +293,70 @@ public: } }; -class GridProxyModel : public QIdentityProxyModel +class GridProxyModel : public QAbstractItemModel { public: + using OptModelIndex = Utils::optional; + GridProxyModel() {} + void setSourceModel(QAbstractItemModel *newModel) + { + if (m_sourceModel == newModel) + return; + if (m_sourceModel) + disconnect(m_sourceModel, nullptr, this, nullptr); + m_sourceModel = newModel; + if (newModel) { + connect(newModel, &QAbstractItemModel::layoutAboutToBeChanged, this, [this] { + layoutAboutToBeChanged(); + }); + connect(newModel, &QAbstractItemModel::layoutChanged, this, [this] { layoutChanged(); }); + connect(newModel, &QAbstractItemModel::modelAboutToBeReset, this, [this] { + beginResetModel(); + }); + connect(newModel, &QAbstractItemModel::modelReset, this, [this] { endResetModel(); }); + connect(newModel, &QAbstractItemModel::rowsAboutToBeInserted, this, [this] { + beginResetModel(); + }); + connect(newModel, &QAbstractItemModel::rowsInserted, this, [this] { endResetModel(); }); + connect(newModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, [this] { + beginResetModel(); + }); + connect(newModel, &QAbstractItemModel::rowsRemoved, this, [this] { endResetModel(); }); + } + } + + QAbstractItemModel *sourceModel() const + { + return m_sourceModel; + } + + QVariant data(const QModelIndex &index, int role) const final + { + const OptModelIndex sourceIndex = mapToSource(index); + if (sourceIndex) + return sourceModel()->data(*sourceIndex, role); + return QVariant(); + } + + Qt::ItemFlags flags(const QModelIndex &index) const final + { + const OptModelIndex sourceIndex = mapToSource(index); + if (sourceIndex) + return sourceModel()->flags(*sourceIndex); + return Qt::ItemFlags(); + } + + bool hasChildren(const QModelIndex &parent) const final + { + const OptModelIndex sourceParent = mapToSource(parent); + if (sourceParent) + return sourceModel()->hasChildren(*sourceParent); + return false; + } + void setColumnCount(int columnCount) { if (columnCount == m_columnCount) @@ -333,15 +391,19 @@ public: return QModelIndex(); } - QModelIndex mapToSource(const QModelIndex &proxyIndex) const final + // The items at the lower right of the grid might not correspond to source items, if + // source's row count is not N*columnCount + OptModelIndex mapToSource(const QModelIndex &proxyIndex) const { if (!proxyIndex.isValid()) return QModelIndex(); int sourceRow = proxyIndex.row() * m_columnCount + proxyIndex.column(); - return sourceModel()->index(sourceRow, 0); + if (sourceRow < sourceModel()->rowCount()) + return sourceModel()->index(sourceRow, 0); + return OptModelIndex(); } - QModelIndex mapFromSource(const QModelIndex &sourceIndex) const final + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const { if (!sourceIndex.isValid()) return QModelIndex(); @@ -352,6 +414,7 @@ public: } private: + QAbstractItemModel *m_sourceModel = nullptr; int m_columnCount = 1; }; -- cgit v1.2.3