summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dietrich-de@nokia.com>2009-10-23 07:14:39 (GMT)
committerGabriel de Dietrich <gabriel.dietrich-de@nokia.com>2009-10-26 09:24:57 (GMT)
commit319482a6b33ce1bd365457054aca49a51d885e07 (patch)
tree84f80d837f8628f6f88bc7cb2f4228970d72b630
parentb14338cce8cb13003a4943d134502e085f36ab08 (diff)
downloadQt-319482a6b33ce1bd365457054aca49a51d885e07.zip
Qt-319482a6b33ce1bd365457054aca49a51d885e07.tar.gz
Qt-319482a6b33ce1bd365457054aca49a51d885e07.tar.bz2
Drag and drop in QListWidget would not preserve the selection
Now, when dropping items, these will remain selected, and in the same visual order as when dragged. Auto-test included for the items moving part. For the rest, it's a drag-and-drop thing. Reviewed-by: Olivier
-rw-r--r--src/gui/itemviews/qlistwidget.cpp31
-rw-r--r--src/gui/itemviews/qlistwidget_p.h3
-rw-r--r--tests/auto/qlistwidget/tst_qlistwidget.cpp59
3 files changed, 80 insertions, 13 deletions
diff --git a/src/gui/itemviews/qlistwidget.cpp b/src/gui/itemviews/qlistwidget.cpp
index a978d0f..5dd1d76 100644
--- a/src/gui/itemviews/qlistwidget.cpp
+++ b/src/gui/itemviews/qlistwidget.cpp
@@ -169,6 +169,20 @@ QListWidgetItem *QListModel::take(int row)
return item;
}
+void QListModel::move(int srcRow, int dstRow)
+{
+ if (srcRow == dstRow
+ || srcRow < 0 || srcRow >= items.count()
+ || dstRow < 0 || dstRow >= items.count())
+ return;
+
+ beginMoveRows(QModelIndex(), srcRow, srcRow, QModelIndex(), dstRow);
+ if (srcRow < dstRow)
+ --dstRow;
+ items.move(srcRow, dstRow);
+ endMoveRows();
+}
+
int QListModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : items.count();
@@ -1804,22 +1818,15 @@ void QListWidget::dropEvent(QDropEvent *event) {
if (persIndexes.contains(topIndex))
return;
+ qSort(persIndexes); // The dropped items will remain in the same visual order.
QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
- QList<QListWidgetItem *> taken;
- for (int i = 0; i < persIndexes.count(); ++i)
- taken.append(takeItem(persIndexes.at(i).row()));
-
- // insert them back in at their new positions
+ int r = row == -1 ? count() : (dropRow.row() >= 0 ? dropRow.row() : row);
for (int i = 0; i < persIndexes.count(); ++i) {
- // Either at a specific point or appended
- if (row == -1) {
- insertItem(count(), taken.takeFirst());
- } else {
- int r = dropRow.row() >= 0 ? dropRow.row() : row;
- insertItem(qMin(r, count()), taken.takeFirst());
- }
+ const QPersistentModelIndex &pIndex = persIndexes.at(i);
+ d->listModel()->move(pIndex.row(), r);
+ r = pIndex.row() + 1; // Dropped items are inserted contiguously and in the right order.
}
event->accept();
diff --git a/src/gui/itemviews/qlistwidget_p.h b/src/gui/itemviews/qlistwidget_p.h
index 69cfa26..b5f28e3 100644
--- a/src/gui/itemviews/qlistwidget_p.h
+++ b/src/gui/itemviews/qlistwidget_p.h
@@ -77,7 +77,7 @@ public:
{ return *i2 < *i1; }
};
-class QListModel : public QAbstractListModel
+class Q_AUTOTEST_EXPORT QListModel : public QAbstractListModel
{
Q_OBJECT
public:
@@ -90,6 +90,7 @@ public:
void insert(int row, const QStringList &items);
void remove(QListWidgetItem *item);
QListWidgetItem *take(int row);
+ void move(int srcRow, int dstRow);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
diff --git a/tests/auto/qlistwidget/tst_qlistwidget.cpp b/tests/auto/qlistwidget/tst_qlistwidget.cpp
index e825c8f..5c6ed54 100644
--- a/tests/auto/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/qlistwidget/tst_qlistwidget.cpp
@@ -46,6 +46,7 @@
#include <qlist.h>
#include <qlistwidget.h>
+#include <private/qlistwidget_p.h>
//TESTED_CLASS=
//TESTED_FILES=
@@ -95,6 +96,8 @@ private slots:
void insertItem();
void insertItems_data();
void insertItems();
+ void moveItemsPriv_data();
+ void moveItemsPriv();
void itemAssignment();
void item_data();
@@ -849,6 +852,62 @@ void tst_QListWidget::removeItems()
}
+void tst_QListWidget::moveItemsPriv_data()
+{
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("srcRow");
+ QTest::addColumn<int>("dstRow");
+ QTest::addColumn<bool>("shouldHaveSignaled");
+
+ QTest::newRow("Empty") << 0 << 0 << 0 << false;
+ QTest::newRow("Overflow src") << 5 << 5 << 2 << false;
+ QTest::newRow("Underflow src") << 5 << -1 << 2 << false;
+ QTest::newRow("Overflow dst") << 5 << 2 << 5 << false;
+ QTest::newRow("Underflow dst") << 5 << 2 << -1 << false;
+ QTest::newRow("Same place") << 5 << 2 << 2 << false;
+ QTest::newRow("Up") << 5 << 4 << 2 << true;
+ QTest::newRow("Down") << 5 << 2 << 4 << true;
+}
+
+void tst_QListWidget::moveItemsPriv()
+{
+ QFETCH(int, rowCount);
+ QFETCH(int, srcRow);
+ QFETCH(int, dstRow);
+ QFETCH(bool, shouldHaveSignaled);
+
+ for (int r = 0; r < rowCount; ++r)
+ new QListWidgetItem(QString::number(r), testWidget);
+
+ QListModel *model = dynamic_cast<QListModel *>(testWidget->model());
+ QVERIFY(model);
+ QSignalSpy beginMoveSpy(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
+ QSignalSpy movedSpy(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ model->move(srcRow, dstRow);
+
+ if (shouldHaveSignaled) {
+ if (srcRow < dstRow)
+ QCOMPARE(testWidget->item(dstRow - 1)->text(), QString::number(srcRow));
+ else
+ QCOMPARE(testWidget->item(dstRow)->text(), QString::number(srcRow));
+
+ QCOMPARE(beginMoveSpy.count(), 1);
+ const QList<QVariant> &beginMoveArgs = beginMoveSpy.takeFirst();
+ QCOMPARE(beginMoveArgs.at(1).toInt(), srcRow);
+ QCOMPARE(beginMoveArgs.at(2).toInt(), srcRow);
+ QCOMPARE(beginMoveArgs.at(4).toInt(), dstRow);
+
+ QCOMPARE(movedSpy.count(), 1);
+ const QList<QVariant> &movedArgs = movedSpy.takeFirst();
+ QCOMPARE(movedArgs.at(1).toInt(), srcRow);
+ QCOMPARE(movedArgs.at(2).toInt(), srcRow);
+ QCOMPARE(movedArgs.at(4).toInt(), dstRow);
+ } else {
+ QCOMPARE(beginMoveSpy.count(), 0);
+ QCOMPARE(movedSpy.count(), 0);
+ }
+}
+
void tst_QListWidget::itemStreaming_data()
{
QTest::addColumn<QString>("text");