Implement QTableWidget/QListWidget::mimeData()

For some reasons lost in history, those methods simply ignore
the list of items passed to them, and always return NULL.
Of course, that's totally broken. Fix that by doing the same thing
that the respective (hidden) models did when calling mimeData().

Surprisingly enough, QTreeWidget has a proper implementation.

Task-number: QTBUG-25900
Change-Id: I99ca7b4d4f87f096fd9ff0b0cb4e58282aa9c26e
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
Giuseppe D'Angelo 2014-09-17 18:08:51 +02:00
parent 0678d7c43c
commit ee17adebd2
6 changed files with 160 additions and 5 deletions

View File

@ -1783,9 +1783,24 @@ QStringList QListWidget::mimeTypes() const
If the list of items is empty, 0 is returned instead of a serialized empty If the list of items is empty, 0 is returned instead of a serialized empty
list. list.
*/ */
QMimeData *QListWidget::mimeData(const QList<QListWidgetItem*>) const QMimeData *QListWidget::mimeData(const QList<QListWidgetItem*> items) const
{ {
return d_func()->listModel()->internalMimeData(); Q_D(const QListWidget);
QModelIndexList &cachedIndexes = d->listModel()->cachedIndexes;
// if non empty, it's called from the model's own mimeData
if (cachedIndexes.isEmpty()) {
foreach (QListWidgetItem *item, items)
cachedIndexes << indexFromItem(item);
QMimeData *result = d->listModel()->internalMimeData();
cachedIndexes.clear();
return result;
}
return d->listModel()->internalMimeData();
} }
#ifndef QT_NO_DRAGANDDROP #ifndef QT_NO_DRAGANDDROP

View File

@ -72,6 +72,8 @@ public:
class Q_AUTOTEST_EXPORT QListModel : public QAbstractListModel class Q_AUTOTEST_EXPORT QListModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
friend class QListWidget;
public: public:
QListModel(QListWidget *parent); QListModel(QListWidget *parent);
~QListModel(); ~QListModel();

View File

@ -2553,9 +2553,24 @@ QStringList QTableWidget::mimeTypes() const
If the list of items is empty, 0 is returned rather than a serialized If the list of items is empty, 0 is returned rather than a serialized
empty list. empty list.
*/ */
QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*>) const QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*> items) const
{ {
return d_func()->tableModel()->internalMimeData(); Q_D(const QTableWidget);
QModelIndexList &cachedIndexes = d->tableModel()->cachedIndexes;
// if non empty, it's called from the model's own mimeData
if (cachedIndexes.isEmpty()) {
foreach (QTableWidgetItem *item, items)
cachedIndexes << indexFromItem(item);
QMimeData *result = d->tableModel()->internalMimeData();
cachedIndexes.clear();
return result;
}
return d->tableModel()->internalMimeData();
} }
/*! /*!

View File

@ -82,6 +82,8 @@ public:
class QTableModel : public QAbstractTableModel class QTableModel : public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
friend class QTableWidget;
public: public:
enum ItemFlagsExtension { enum ItemFlagsExtension {
ItemIsHeaderItem = 128 ItemIsHeaderItem = 128

View File

@ -123,7 +123,7 @@ private slots:
void task258949_keypressHangup(); void task258949_keypressHangup();
void QTBUG8086_currentItemChangedOnClick(); void QTBUG8086_currentItemChangedOnClick();
void QTBUG14363_completerWithAnyKeyPressedEditTriggers(); void QTBUG14363_completerWithAnyKeyPressedEditTriggers();
void mimeData();
protected slots: protected slots:
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last) void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
@ -1082,6 +1082,9 @@ public:
Q_UNUSED(item); Q_UNUSED(item);
return QListWidget::state() == QListWidget::EditingState; return QListWidget::state() == QListWidget::EditingState;
} }
using QListWidget::mimeData;
using QListWidget::indexFromItem;
}; };
void tst_QListWidget::closeEditor() void tst_QListWidget::closeEditor()
@ -1662,7 +1665,57 @@ void tst_QListWidget::QTBUG14363_completerWithAnyKeyPressedEditTriggers()
QCOMPARE(le->completer()->currentCompletion(), QString("completer")); QCOMPARE(le->completer()->currentCompletion(), QString("completer"));
} }
void tst_QListWidget::mimeData()
{
TestListWidget list;
for (int x = 0; x < 10; ++x) {
QListWidgetItem *item = new QListWidgetItem(QStringLiteral("123"));
list.addItem(item);
}
QList<QListWidgetItem *> tableWidgetItemList;
QModelIndexList modelIndexList;
// do these checks more than once to ensure that the "cached indexes" work as expected
QVERIFY(!list.mimeData(tableWidgetItemList));
QVERIFY(!list.model()->mimeData(modelIndexList));
QVERIFY(!list.model()->mimeData(modelIndexList));
QVERIFY(!list.mimeData(tableWidgetItemList));
tableWidgetItemList << list.item(1);
modelIndexList << list.indexFromItem(list.item(1));
QMimeData *data;
QVERIFY(data = list.mimeData(tableWidgetItemList));
delete data;
QVERIFY(data = list.model()->mimeData(modelIndexList));
delete data;
QVERIFY(data = list.model()->mimeData(modelIndexList));
delete data;
QVERIFY(data = list.mimeData(tableWidgetItemList));
delete data;
// check the saved data is actually the same
QMimeData *data2;
data = list.mimeData(tableWidgetItemList);
data2 = list.model()->mimeData(modelIndexList);
const QString format = QStringLiteral("application/x-qabstractitemmodeldatalist");
QVERIFY(data->hasFormat(format));
QVERIFY(data2->hasFormat(format));
QVERIFY(data->data(format) == data2->data(format));
delete data;
delete data2;
}
QTEST_MAIN(tst_QListWidget) QTEST_MAIN(tst_QListWidget)
#include "tst_qlistwidget.moc" #include "tst_qlistwidget.moc"

View File

@ -93,6 +93,7 @@ private slots:
void task219380_removeLastRow(); void task219380_removeLastRow();
void task262056_sortDuplicate(); void task262056_sortDuplicate();
void itemWithHeaderItems(); void itemWithHeaderItems();
void mimeData();
private: private:
QTableWidget *testWidget; QTableWidget *testWidget;
@ -1497,5 +1498,72 @@ void tst_QTableWidget::itemWithHeaderItems()
QCOMPARE(table.item(0, 1), static_cast<QTableWidgetItem *>(0)); QCOMPARE(table.item(0, 1), static_cast<QTableWidgetItem *>(0));
} }
class TestTableWidget : public QTableWidget
{
Q_OBJECT
public:
TestTableWidget(int rows, int columns, QWidget *parent = 0)
: QTableWidget(rows, columns, parent)
{
}
using QTableWidget::mimeData;
using QTableWidget::indexFromItem;
};
void tst_QTableWidget::mimeData()
{
TestTableWidget table(10, 10);
for (int x = 0; x < 10; ++x) {
for (int y = 0; y < 10; ++y) {
QTableWidgetItem *item = new QTableWidgetItem(QStringLiteral("123"));
table.setItem(y, x, item);
}
}
QList<QTableWidgetItem *> tableWidgetItemList;
QModelIndexList modelIndexList;
// do these checks more than once to ensure that the "cached indexes" work as expected
QVERIFY(!table.mimeData(tableWidgetItemList));
QVERIFY(!table.model()->mimeData(modelIndexList));
QVERIFY(!table.model()->mimeData(modelIndexList));
QVERIFY(!table.mimeData(tableWidgetItemList));
tableWidgetItemList << table.item(1, 1);
modelIndexList << table.indexFromItem(table.item(1, 1));
QMimeData *data;
QVERIFY(data = table.mimeData(tableWidgetItemList));
delete data;
QVERIFY(data = table.model()->mimeData(modelIndexList));
delete data;
QVERIFY(data = table.model()->mimeData(modelIndexList));
delete data;
QVERIFY(data = table.mimeData(tableWidgetItemList));
delete data;
// check the saved data is actually the same
QMimeData *data2;
data = table.mimeData(tableWidgetItemList);
data2 = table.model()->mimeData(modelIndexList);
const QString format = QStringLiteral("application/x-qabstractitemmodeldatalist");
QVERIFY(data->hasFormat(format));
QVERIFY(data2->hasFormat(format));
QVERIFY(data->data(format) == data2->data(format));
delete data;
delete data2;
}
QTEST_MAIN(tst_QTableWidget) QTEST_MAIN(tst_QTableWidget)
#include "tst_qtablewidget.moc" #include "tst_qtablewidget.moc"