Implement clearItemData in common models

A virtual method clearItemData was added to QAIM for Qt6.
This patch implements that method to all Qt concrete models for which
it makes sense.

Task-number: QTBUG-69616
Change-Id: If980fcfc36f723128bc56ec4587c5c3a338dbbcc
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
Luca Beldi 2018-09-03 10:13:53 +01:00
parent e5d0289413
commit 551e11c286
16 changed files with 202 additions and 1 deletions

View File

@ -313,6 +313,17 @@ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation
return d->model->setHeaderData(sourceSection, orientation, value, role); return d->model->setHeaderData(sourceSection, orientation, value, role);
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
/*!
\reimp
*/
bool QAbstractProxyModel::clearItemData(const QModelIndex &index)
{
Q_D(QAbstractProxyModel);
return d->model->clearItemData(mapToSource(index));
}
#endif
/*! /*!
\reimp \reimp
*/ */

View File

@ -78,6 +78,9 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
bool setItemData(const QModelIndex& index, const QMap<int, QVariant> &roles) override; bool setItemData(const QModelIndex& index, const QMap<int, QVariant> &roles) override;
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override; bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool clearItemData(const QModelIndex &index) override;
#endif
QModelIndex buddy(const QModelIndex &index) const override; QModelIndex buddy(const QModelIndex &index) const override;
bool canFetchMore(const QModelIndex &parent) const override; bool canFetchMore(const QModelIndex &parent) const override;

View File

@ -197,6 +197,16 @@ bool QStringListModel::setData(const QModelIndex &index, const QVariant &value,
return false; return false;
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
/*!
\reimp
*/
bool QStringListModel::clearItemData(const QModelIndex &index)
{
return setData(index, QVariant(), Qt::EditRole);
}
#endif
/*! /*!
Inserts \a count rows into the model, beginning at the given \a row. Inserts \a count rows into the model, beginning at the given \a row.

View File

@ -59,6 +59,9 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool clearItemData(const QModelIndex &index) override;
#endif
Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override;

View File

@ -3005,11 +3005,17 @@ bool QStandardItemModel::setData(const QModelIndex &index, const QVariant &value
return true; return true;
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
/*!
\reimp
*/
#else
/*! /*!
\since 5.12 \since 5.12
Removes the data stored in all the roles for the given \a index. Removes the data stored in all the roles for the given \a index.
\sa setData(), data() \sa setData(), data()
*/ */
#endif
bool QStandardItemModel::clearItemData(const QModelIndex &index) bool QStandardItemModel::clearItemData(const QModelIndex &index)
{ {
if (!checkIndex(index, CheckIndexOption::IndexIsValid)) if (!checkIndex(index, CheckIndexOption::IndexIsValid))

View File

@ -607,6 +607,16 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in
return true; return true;
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
/*!
\reimp
*/
bool QStringListModel::clearItemData(const QModelIndex &index)
{
return setData(index, QVariant(), Qt::EditRole);
}
#endif
/*! /*!
This function simply calls QSqlQueryModel::setQuery(\a query). This function simply calls QSqlQueryModel::setQuery(\a query).
You should normally not call it on a QSqlTableModel. Instead, use You should normally not call it on a QSqlTableModel. Instead, use

View File

@ -74,6 +74,9 @@ public:
QSqlRecord record(int row) const; QSqlRecord record(int row) const;
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool clearItemData(const QModelIndex &index) override;
#endif
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;

View File

@ -227,6 +227,22 @@ bool QListModel::setData(const QModelIndex &index, const QVariant &value, int ro
return true; return true;
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QListModel::clearItemData(const QModelIndex &index)
{
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
return false;
QListWidgetItem *item = items.at(index.row());
const auto beginIter = item->d->values.cbegin();
const auto endIter = item->d->values.cend();
if (std::all_of(beginIter, endIter, [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); }))
return true; //it's already cleared
item->d->values.clear();
emit dataChanged(index, index, QVector<int>{});
return true;
}
#endif
QMap<int, QVariant> QListModel::itemData(const QModelIndex &index) const QMap<int, QVariant> QListModel::itemData(const QModelIndex &index) const
{ {
QMap<int, QVariant> roles; QMap<int, QVariant> roles;

View File

@ -100,6 +100,9 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool setData(const QModelIndex &index, const QVariant &value, int role) override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool clearItemData(const QModelIndex &index) override;
#endif
QMap<int, QVariant> itemData(const QModelIndex &index) const override; QMap<int, QVariant> itemData(const QModelIndex &index) const override;

View File

@ -480,6 +480,24 @@ bool QTableModel::setItemData(const QModelIndex &index, const QMap<int, QVariant
return true; return true;
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QTableModel::clearItemData(const QModelIndex &index)
{
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
return false;
QTableWidgetItem *itm = item(index);
if (!itm)
return false;
const auto beginIter = itm->values.cbegin();
const auto endIter = itm->values.cend();
if (std::all_of(beginIter, endIter, [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); }))
return true; //it's already cleared
itm->values.clear();
emit dataChanged(index, index, QVector<int>{});
return true;
}
#endif
Qt::ItemFlags QTableModel::flags(const QModelIndex &index) const Qt::ItemFlags QTableModel::flags(const QModelIndex &index) const
{ {
if (!index.isValid()) if (!index.isValid())

View File

@ -129,6 +129,9 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool setData(const QModelIndex &index, const QVariant &value, int role) override;
bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override; bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool clearItemData(const QModelIndex &index) override;
#endif
QMap<int, QVariant> itemData(const QModelIndex &index) const override; QMap<int, QVariant> itemData(const QModelIndex &index) const override;

View File

@ -390,6 +390,27 @@ bool QTreeModel::setData(const QModelIndex &index, const QVariant &value, int ro
return false; return false;
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QTreeModel::clearItemData(const QModelIndex &index)
{
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
return false;
QTreeWidgetItem *itm = item(index);
if (!itm)
return false;
const auto beginIter = itm->values.at(index.column()).cbegin();
const auto endIter = itm->values.at(index.column()).cend();
if (std::all_of(beginIter, endIter, [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); })
&& !itm->d->display.at(index.column()).isValid()) {
return true; //it's already cleared
}
itm->d->display[index.column()] = QVariant();
itm->values[index.column()].clear();
emit dataChanged(index, index, QVector<int>{});
return true;
}
#endif
QMap<int, QVariant> QTreeModel::itemData(const QModelIndex &index) const QMap<int, QVariant> QTreeModel::itemData(const QModelIndex &index) const
{ {
QMap<int, QVariant> roles; QMap<int, QVariant> roles;

View File

@ -99,7 +99,9 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool setData(const QModelIndex &index, const QVariant &value, int role) override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool clearItemData(const QModelIndex &index) override;
#endif
QMap<int, QVariant> itemData(const QModelIndex &index) const override; QMap<int, QVariant> itemData(const QModelIndex &index) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override;

View File

@ -116,6 +116,9 @@ private slots:
void QTBUG14363_completerWithAnyKeyPressedEditTriggers(); void QTBUG14363_completerWithAnyKeyPressedEditTriggers();
void mimeData(); void mimeData();
void QTBUG50891_ensureSelectionModelSignalConnectionsAreSet(); void QTBUG50891_ensureSelectionModelSignalConnectionsAreSet();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void clearItemData();
#endif
protected slots: protected slots:
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last) void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
@ -1743,5 +1746,27 @@ void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet()
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void tst_QListWidget::clearItemData()
{
QListWidget list;
for (int i = 0 ; i < 4; ++i)
new QListWidgetItem(QString::number(i), &list);
QSignalSpy dataChangeSpy(list.model(), &QAbstractItemModel::dataChanged);
QVERIFY(dataChangeSpy.isValid());
QVERIFY(!list.model()->clearItemData(QModelIndex()));
QCOMPARE(dataChangeSpy.size(), 0);
QVERIFY(list.model()->clearItemData(list.model()->index(0, 0)));
QVERIFY(!list.model()->index(0, 0).data().isValid());
QCOMPARE(dataChangeSpy.size(), 1);
const QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst();
QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), list.model()->index(0, 0));
QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), list.model()->index(0, 0));
QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty());
QVERIFY(list.model()->clearItemData(list.model()->index(0, 0)));
QCOMPARE(dataChangeSpy.size(), 0);
}
#endif
QTEST_MAIN(tst_QListWidget) QTEST_MAIN(tst_QListWidget)
#include "tst_qlistwidget.moc" #include "tst_qlistwidget.moc"

View File

@ -89,6 +89,9 @@ private slots:
void itemWithHeaderItems(); void itemWithHeaderItems();
void mimeData(); void mimeData();
void selectedRowAfterSorting(); void selectedRowAfterSorting();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void clearItemData();
#endif
private: private:
QTableWidget *testWidget; QTableWidget *testWidget;
@ -1610,5 +1613,28 @@ void tst_QTableWidget::selectedRowAfterSorting()
} }
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void tst_QTableWidget::clearItemData()
{
QTableWidget table(3,3);
for (int r = 0; r < 3; r++)
for (int c = 0; c < 3; c++)
table.setItem(r,c,new QTableWidgetItem(QStringLiteral("0")));
QSignalSpy dataChangeSpy(table.model(), &QAbstractItemModel::dataChanged);
QVERIFY(dataChangeSpy.isValid());
QVERIFY(!table.model()->clearItemData(QModelIndex()));
QCOMPARE(dataChangeSpy.size(), 0);
QVERIFY(table.model()->clearItemData(table.model()->index(0, 0)));
QVERIFY(!table.model()->index(0, 0).data().isValid());
QCOMPARE(dataChangeSpy.size(), 1);
const QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst();
QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), table.model()->index(0, 0));
QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), table.model()->index(0, 0));
QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty());
QVERIFY(table.model()->clearItemData(table.model()->index(0, 0)));
QCOMPARE(dataChangeSpy.size(), 0);
}
#endif
QTEST_MAIN(tst_QTableWidget) QTEST_MAIN(tst_QTableWidget)
#include "tst_qtablewidget.moc" #include "tst_qtablewidget.moc"

View File

@ -161,6 +161,9 @@ private slots:
void getMimeDataWithInvalidItem(); void getMimeDataWithInvalidItem();
void testVisualItemRect(); void testVisualItemRect();
void reparentHiddenItem(); void reparentHiddenItem();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void clearItemData();
#endif
public slots: public slots:
void itemSelectionChanged(); void itemSelectionChanged();
@ -3529,5 +3532,43 @@ void tst_QTreeWidget::reparentHiddenItem()
QVERIFY(grandChild->isHidden()); QVERIFY(grandChild->isHidden());
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void tst_QTreeWidget::clearItemData()
{
QTreeWidget tree;
QAbstractItemModel* model = tree.model();
QVERIFY(model->insertColumn(0));
QVERIFY(model->insertRow(0));
const QModelIndex parentIdx = model->index(0, 0);
QVERIFY(model->insertColumn(0, parentIdx));
QVERIFY(model->insertRow(0, parentIdx));
const QModelIndex childIdx = model->index(0, 0, parentIdx);
model->setData(parentIdx, QStringLiteral("parent"));
model->setData(parentIdx, QStringLiteral("parent"), Qt::UserRole);
model->setData(childIdx, QStringLiteral("child"));
QSignalSpy dataChangeSpy(model, &QAbstractItemModel::dataChanged);
QVERIFY(dataChangeSpy.isValid());
QVERIFY(!model->clearItemData(QModelIndex()));
QCOMPARE(dataChangeSpy.size(), 0);
QVERIFY(model->clearItemData(parentIdx));
QVERIFY(!model->data(parentIdx).isValid());
QVERIFY(!model->data(parentIdx, Qt::UserRole).isValid());
QCOMPARE(dataChangeSpy.size(), 1);
QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst();
QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), parentIdx);
QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), parentIdx);
QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty());
QVERIFY(model->clearItemData(parentIdx));
QCOMPARE(dataChangeSpy.size(), 0);
QVERIFY(model->clearItemData(childIdx));
QVERIFY(!model->data(childIdx).isValid());
QCOMPARE(dataChangeSpy.size(), 1);
dataChangeArgs = dataChangeSpy.takeFirst();
QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), childIdx);
QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), childIdx);
QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty());
}
#endif
QTEST_MAIN(tst_QTreeWidget) QTEST_MAIN(tst_QTreeWidget)
#include "tst_qtreewidget.moc" #include "tst_qtreewidget.moc"