KSPM: Fix behavior when a selection is made while resetting.

The KSPM should never clear or reset the selection of the
QItemSelectionModel it refers to.  It should be a read-only view on
that selection.  If the selection changes while the source is being
reset, ignore that selection change.  The proxy will clear its own
cached data when it processes the modelReset signal from the model,
and will populate itself with the selection as it is at that point.
wilder
Stephen Kelly 11 years ago
parent 9ba41df61b
commit 41b8a5fc84
  1. 1
      autotests/CMakeLists.txt
  2. 51
      autotests/kselectionproxymodeltest.cpp
  3. 14
      src/kselectionproxymodel.cpp

@ -18,6 +18,7 @@ ecm_add_tests(
kdescendantsproxymodel_smoketest.cpp
klinkitemselectionmodeltest.cpp
testmodelqueuedconnections.cpp
kselectionproxymodeltest.cpp
LINK_LIBRARIES KF5::ItemModels Qt5::Test Qt5::Widgets proxymodeltestsuite
)

@ -0,0 +1,51 @@
#include <QTest>
#include <QStringListModel>
#include <kselectionproxymodel.h>
class KSelectionProxyModelTest : public QObject
{
Q_OBJECT
public:
KSelectionProxyModelTest(QObject* parent = 0)
: QObject(parent)
{
}
private Q_SLOTS:
void selectOnSourceReset();
};
void KSelectionProxyModelTest::selectOnSourceReset()
{
QStringListModel strings({
"Monday",
"Tuesday",
"Wednesday",
"Thursday"
});
QItemSelectionModel selectionModel(&strings);
connect(&strings, &QAbstractItemModel::modelReset, [&] {
selectionModel.select(QItemSelection(strings.index(0, 0), strings.index(2, 0)),
QItemSelectionModel::Select);
});
KSelectionProxyModel proxy(&selectionModel);
proxy.setSourceModel(&strings);
selectionModel.select(QItemSelection(strings.index(0, 0), strings.index(2, 0)),
QItemSelectionModel::Select);
strings.setStringList({ "One", "Two", "Three", "Four" });
QVERIFY(selectionModel.selection().contains(strings.index(0, 0)));
QVERIFY(selectionModel.selection().contains(strings.index(1, 0)));
QVERIFY(selectionModel.selection().contains(strings.index(2, 0)));
}
QTEST_MAIN(KSelectionProxyModelTest)
#include "kselectionproxymodeltest.moc"

@ -439,6 +439,7 @@ public:
m_rowsRemoved(false),
m_rowsMoved(false),
m_resetting(false),
m_sourceModelResetting(false),
m_doubleResetting(false),
m_layoutChanging(false),
m_ignoreNextLayoutAboutToBeChanged(false),
@ -621,6 +622,7 @@ public:
QPair<int, int> m_proxyRemoveRows;
bool m_rowsMoved;
bool m_resetting;
bool m_sourceModelResetting;
bool m_doubleResetting;
bool m_layoutChanging;
bool m_ignoreNextLayoutAboutToBeChanged;
@ -863,6 +865,7 @@ void KSelectionProxyModelPrivate::sourceModelDestroyed()
// There is very little we can do here.
resetInternalData();
m_resetting = false;
m_sourceModelResetting = false;
}
void KSelectionProxyModelPrivate::sourceModelAboutToBeReset()
@ -887,6 +890,7 @@ void KSelectionProxyModelPrivate::sourceModelAboutToBeReset()
q->beginResetModel();
m_resetting = true;
m_sourceModelResetting = true;
}
void KSelectionProxyModelPrivate::sourceModelReset()
@ -899,11 +903,7 @@ void KSelectionProxyModelPrivate::sourceModelReset()
}
resetInternalData();
// No need to try to refill this. When the model is reset it doesn't have a meaningful selection anymore,
// but when it gets one we'll be notified anyway.
if (!m_selectionModel.isNull()) {
m_selectionModel.data()->reset();
}
m_sourceModelResetting = false;
m_resetting = false;
q->endResetModel();
}
@ -1860,6 +1860,10 @@ void KSelectionProxyModelPrivate::selectionChanged(const QItemSelection &_select
return;
}
if (m_sourceModelResetting) {
return;
}
if (m_rowsInserted || m_rowsRemoved) {
m_pendingSelectionChanges.append(PendingSelectionChange(_selected, _deselected));
return;

Loading…
Cancel
Save