PDA

View Full Version : Workaround for StandardItemModel drag drop bug



onamatic
7th November 2008, 12:09
I have a QTreeView with a QStandardItemModel implementing a simple "notebook" type of application (ie: a bunch of notes inside a bunch of folders).

Everything is fine except for internally drag/dropping a folder in the treeview when all the notes in the dragged folder get lost.
This is a known bug and is detailed here: Drag and drop in QTreeView with QStandardItemModel and InternalMove loses children (http://trolltech.com/developer/task-tracker/index_html?method=entry&id=227426)

Without this functionality I'm truly stuck, so I'm now subclassing QStandardItemModel
class QNotesStandardItemModel : public QStandardItemModel
and trying to manually sort things out in:

bool QNotesStandardItemModel::dropMimeData ( const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent ){
QStringList list = data->formats();
if (!data->hasFormat("application/x-qabstractitemmodeldatalist")) return false;
QByteArray encodedData = data->data("application/x-qabstractitemmodeldatalist");

And now I'm stuck!
QUESTION 1: encodedData contains a QList<QModelIndex> but how do I get at it? I want a kind of "qobject_cast<QModelIndexList>(encodedData)" type of thing! Just can't see how though.

QUESTION 2: Is there an easy way of working round the "lost children" problem? I really wanted to keep this application as simple as possible and not have to subclass standard classes which generally work fine out of the box.

caduel
7th November 2008, 17:57
Re Q1:
If you use drag-n-drop between two different applications, the QModelIndexes will not be of much use to you.
If you drag within a single application, just create a subclass of QDrag or QMimeData and add a QList<QModelIndex> to it. Then (at the drop site) cast the object back to your class and access the QModelIndexes. (No need to go through encode/decode troubles within a single application.)

HTH

onamatic
7th November 2008, 19:02
Thanks for helping me Caduel!


Re Q1:
If you use drag-n-drop between two different applications, the QModelIndexes will not be of much use to you. Understood, I'm only drag-n-dropping inside a single treeview so that's fine.


...Then (at the drop site) cast the object back to your class and access the QModelIndexes. (No need to go through encode/decode troubles within a single application.) There's my problem - I can't see how to cast from the QByteArray returned by the call to mimeDataPtr->data() to the "application/x-qabstractitemmodeldatalist" that I want. I'm missing something conceptually here I think!

caduel
8th November 2008, 08:37
I was suggesting to not use that QByteArray at all.


class MyMimeData : public QMimeData
{
QModelIndexList indexes;
public:
MyMimeData(const QModelIndexList & indexes)
: indexes_(indexes)
{}
const QModelIndexList & indexes() const { return indexes_; }
};

QMimeData * QNotesStandardItemModel::mimeData(const QModelIndexList &indexes) const
{
// maybe set a mimetype...
// but finally
return new MyMimeData(indexes);
}

bool QNotesStandardItemModel::dropMimeData ( const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent )
{
if (MyMimeData *mmd = qobject_cast<MyMimeData>(data))
{
// access dragges indexes as: mmd->indexes()
// ...
return true;
}
return false;
}

HTH

onamatic
9th November 2008, 21:50
That works brilliantly. Thank you very much Caduel for taking the time to write my code for me! Much appreciated.

Bob