PDA

View Full Version : How to reorder items in QListView?



xfurrier
12th August 2009, 13:00
I want to rearrange/reorder items by dragging and dropping - which I can do, but with some unwanted side-effects. I've tried adjusting numerous options in order to fix the problem, but to no avail. This is now driving me crazy. Any help would be greatly appreciated.

I'm using model/view classes (QStringListModel and QListView) and can rearrange the items, e.g. drag "ID" to the top of the list. I can do that, but only if I'm careful. The unwanted side-effect is that I can easily overwrite another item if my mouse is not placed exactly between the items. For example, if I drag "ID" and drop it over "Name", the list will shrink, with "Name" nowhere to be seen again.

I've also tried subclassing QStringListModel and changing flags, but still no luck.

How can I eliminate this overwriting effect? I just want pure and simple reordering without losing any items.

A sample code is below. Thanks.



#include <QtGui>
#include <QApplication>

class MyListModel : public QStringListModel
{
public:
MyListModel(const QStringList &strings, QObject *parent = 0 );
Qt::ItemFlags flags(const QModelIndex&index) const;
};

MyListModel::MyListModel(const QStringList &strings, QObject *parent) : QStringListModel(strings, parent)
{
}

Qt::ItemFlags MyListModel::flags(const QModelIndex&index) const
{
Qt::ItemFlags flags = QStringListModel::flags(index);
// flags = Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled;
flags = Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
return flags;
}



int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QListView list;
list.setViewMode(QListView::ListMode);
list.setMovement(QListView::Snap);
list.setDragDropMode(QAbstractItemView::InternalMo ve);
list.setDragDropOverwriteMode(false);

QStringListModel model(QStringList() << "Name" << "Surname" << "ID");
// MyListModel model(QStringList() << "Name" << "Surname" << "ID");
list.setModel(&model);
list.show();

return a.exec();
}

numbat
12th August 2009, 13:57
You still want the root index to accepts drops, just not the items so try:


Qt::ItemFlags MyListModel::flags(const QModelIndex&index) const
{
Qt::ItemFlags flags; //= QStringListModel::flags(index);

if (index.isValid())
flags = Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled;
else
flags = Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;

return flags;
}

This will work if the root index is invalid (as it usually is). However, if you use setRootIndex you may have to compare against that index instead.

xfurrier
12th August 2009, 17:09
exactly what I wanted. thanx.