PDA

View Full Version : QStandardItemModel drag and drop



justin123
24th May 2012, 04:08
I have a tree view of resource types that consists of:
Sprites
Backgrounds
Tilesets
Sounds
Objects
Markers
Maps

Using QStandardItemModel's default drag and drop, it allows items to be dropped anywhere meaning that I could mix resource types by dragging a sprite resource into the backgrounds item. To prevent this I tried reimplementing mimeTypes(), mimeData(), and dropMimeData(). When mimeData is reimplemented, for some reason drops are not being accepted even if setAcceptDrops is set to true, but if I comment it out, drops are magically accepted again but are unreadable. What could be the problem?

ResourceModel.h

class ResourceModel : public QStandardItemModel
{
Q_OBJECT
public:
explicit ResourceModel( QObject *parent, Document *doc, bool createTree = true);

QModelIndex AddResource( Resource *res, QModelIndex *pParent = NULL);
void AddGroup( QModelIndex parent);

friend class Document;
friend class Resource;
friend class Sprite;
friend class Background;
friend class Tileset;
friend class Sounds;
friend class Object;
friend class Map;
friend class CollisionMask;
friend class Marker;

protected:
Qt::ItemFlags flags(const QModelIndex &index) const;

Qt::DropActions supportedDropActions() const
{
return Qt::MoveAction;
}

QStringList mimeTypes();
QMimeData *mimeData(const QModelIndexList &indexes) const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);

private:
Document *document;
QStandardItem *root;
QStandardItem *Sprites;
QStandardItem *Backgrounds;
QStandardItem *Tilesets;
QStandardItem *Sounds;
QStandardItem *Objects;
QStandardItem *CollisionMasks;
QStandardItem *Markers;
QStandardItem *Maps;

int sprCount, bgCount, tlsCount, sndCount, objCount, collisionMaskCount, mapCount, markerCount;
};

ResourceModel.cpp

#include "resourcemodel.h"
#include "document.h"

ResourceModel::ResourceModel(QObject *parent, Document *doc, bool createTree) :
QStandardItemModel(parent), document( doc)
{
if (createTree)
{
root = invisibleRootItem();
Sprites = new QStandardItem( "Sprites");
Backgrounds = new QStandardItem( "Backgrounds");
Tilesets = new QStandardItem("Tilesets");
Sounds = new QStandardItem( "Sounds");
Objects = new QStandardItem( "Objects");
CollisionMasks = new QStandardItem( "Collision Masks");
Markers = new QStandardItem( "Markers");
Maps = new QStandardItem( "Maps");

Sprites->setEditable( false);
Sprites->setData( QVariant(Resource_Sprite), Qt::UserRole+1);
Sprites->setData( QVariant( -1), Qt::UserRole+2);
Sprites->setData( QVariant( true), Qt::UserRole+3);
Sprites->setData( QVariant( true), Qt::UserRole+4);

Backgrounds->setEditable( false);
Backgrounds->setData( QVariant(Resource_Background), Qt::UserRole+1);
Backgrounds->setData( QVariant( -1), Qt::UserRole+2);
Backgrounds->setData( QVariant( true), Qt::UserRole+3);
Backgrounds->setData( QVariant( true), Qt::UserRole+4);

Tilesets->setEditable( false);
Tilesets->setData( QVariant(Resource_Tileset), Qt::UserRole+1);
Tilesets->setData( QVariant( -1), Qt::UserRole+2);
Tilesets->setData( QVariant( true), Qt::UserRole+3);
Tilesets->setData( QVariant( true), Qt::UserRole+4);

Sounds->setEditable( false);
Sounds->setData( QVariant(Resource_Sound), Qt::UserRole+1);
Sounds->setData( QVariant( -1), Qt::UserRole+2);
Sounds->setData( QVariant( true), Qt::UserRole+3);
Sounds->setData( QVariant( true), Qt::UserRole+4);

Objects->setEditable( false);
Objects->setData( QVariant(Resource_Object), Qt::UserRole+1);
Objects->setData( QVariant( -1), Qt::UserRole+2);
Objects->setData( QVariant( true), Qt::UserRole+3);
Objects->setData( QVariant( true), Qt::UserRole+4);

CollisionMasks->setEditable( false);
CollisionMasks->setData( QVariant(Resource_Collision_Mask), Qt::UserRole+1);
CollisionMasks->setData( QVariant( -1), Qt::UserRole+2);
CollisionMasks->setData( QVariant( true), Qt::UserRole+3);
CollisionMasks->setData( QVariant( true), Qt::UserRole+4);

Markers->setEditable( false);
Markers->setData( QVariant(Resource_Marker), Qt::UserRole+1);
Markers->setData( QVariant( -1), Qt::UserRole+2);
Markers->setData( QVariant( true), Qt::UserRole+3);
Markers->setData( QVariant( true), Qt::UserRole+4);

Maps->setEditable( false);
Maps->setData( QVariant(Resource_Map), Qt::UserRole+1);
Maps->setData( QVariant( -1), Qt::UserRole+2);
Maps->setData( QVariant( true), Qt::UserRole+3);
Maps->setData( QVariant( true), Qt::UserRole+4);

root->appendRow( Sprites);
root->appendRow( Backgrounds);
root->appendRow( Tilesets);
root->appendRow( Sounds);
root->appendRow( Objects);
root->appendRow( CollisionMasks);
root->appendRow( Markers);
root->appendRow( Maps);
}

sprCount = bgCount = tlsCount = sndCount = objCount = collisionMaskCount = markerCount = mapCount = 0;
}

Qt::ItemFlags ResourceModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags flags = QStandardItemModel::flags( index);

if (!index.isValid())
return flags;

if (!index.data( Qt::UserRole+4).toBool())
{
flags |= Qt::ItemIsDragEnabled;
}

if (index.data( Qt::UserRole+3).toBool())
{
flags |= Qt::ItemIsDropEnabled;
}

return flags;
}

QStringList ResourceModel::mimeTypes()
{
QStringList list;
list << "resource/index";
return list;
}

QMimeData *ResourceModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QByteArray encodedData;

QDataStream stream(&encodedData, QIODevice::WriteOnly);

foreach (const QModelIndex &index, indexes)
{
if (index.isValid())
{
stream << index.data( Qt::UserRole+1);
itemFromIndex( index)->write( stream);
}
}

mimeData->setData("resource/index", encodedData);
return mimeData;
}

bool ResourceModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
QByteArray encodedData = data->data("resource/index");
QDataStream stream(&encodedData, QIODevice::ReadOnly);

if (action == Qt::IgnoreAction)
return true;

if (encodedData.isEmpty())
return false;

int type;
stream >> type;

if (!data->hasFormat("resource/index") && ( type != parent.data( Qt::UserRole+1).toInt()))
return false;

if (column > 0)
return false;

int beginRow;

if (row != -1)
beginRow = row;
else if (parent.isValid())
beginRow = parent.row();
else
beginRow = rowCount(QModelIndex());

QStandardItem *item = new QStandardItem;
item->read( stream);

insertRow( beginRow, item);

return true;
}