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
Qt Code:
  1. class ResourceModel : public QStandardItemModel
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit ResourceModel( QObject *parent, Document *doc, bool createTree = true);
  6.  
  7. QModelIndex AddResource( Resource *res, QModelIndex *pParent = NULL);
  8. void AddGroup( QModelIndex parent);
  9.  
  10. friend class Document;
  11. friend class Resource;
  12. friend class Sprite;
  13. friend class Background;
  14. friend class Tileset;
  15. friend class Sounds;
  16. friend class Object;
  17. friend class Map;
  18. friend class CollisionMask;
  19. friend class Marker;
  20.  
  21. protected:
  22. Qt::ItemFlags flags(const QModelIndex &index) const;
  23.  
  24. Qt::DropActions supportedDropActions() const
  25. {
  26. return Qt::MoveAction;
  27. }
  28.  
  29. QStringList mimeTypes();
  30. QMimeData *mimeData(const QModelIndexList &indexes) const;
  31. bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
  32.  
  33. private:
  34. Document *document;
  35. QStandardItem *Sprites;
  36. QStandardItem *Backgrounds;
  37. QStandardItem *Tilesets;
  38. QStandardItem *Sounds;
  39. QStandardItem *Objects;
  40. QStandardItem *CollisionMasks;
  41. QStandardItem *Markers;
  42.  
  43. int sprCount, bgCount, tlsCount, sndCount, objCount, collisionMaskCount, mapCount, markerCount;
  44. };
To copy to clipboard, switch view to plain text mode 

ResourceModel.cpp
Qt Code:
  1. #include "resourcemodel.h"
  2. #include "document.h"
  3.  
  4. ResourceModel::ResourceModel(QObject *parent, Document *doc, bool createTree) :
  5. QStandardItemModel(parent), document( doc)
  6. {
  7. if (createTree)
  8. {
  9. root = invisibleRootItem();
  10. Sprites = new QStandardItem( "Sprites");
  11. Backgrounds = new QStandardItem( "Backgrounds");
  12. Tilesets = new QStandardItem("Tilesets");
  13. Sounds = new QStandardItem( "Sounds");
  14. Objects = new QStandardItem( "Objects");
  15. CollisionMasks = new QStandardItem( "Collision Masks");
  16. Markers = new QStandardItem( "Markers");
  17. Maps = new QStandardItem( "Maps");
  18.  
  19. Sprites->setEditable( false);
  20. Sprites->setData( QVariant(Resource_Sprite), Qt::UserRole+1);
  21. Sprites->setData( QVariant( -1), Qt::UserRole+2);
  22. Sprites->setData( QVariant( true), Qt::UserRole+3);
  23. Sprites->setData( QVariant( true), Qt::UserRole+4);
  24.  
  25. Backgrounds->setEditable( false);
  26. Backgrounds->setData( QVariant(Resource_Background), Qt::UserRole+1);
  27. Backgrounds->setData( QVariant( -1), Qt::UserRole+2);
  28. Backgrounds->setData( QVariant( true), Qt::UserRole+3);
  29. Backgrounds->setData( QVariant( true), Qt::UserRole+4);
  30.  
  31. Tilesets->setEditable( false);
  32. Tilesets->setData( QVariant(Resource_Tileset), Qt::UserRole+1);
  33. Tilesets->setData( QVariant( -1), Qt::UserRole+2);
  34. Tilesets->setData( QVariant( true), Qt::UserRole+3);
  35. Tilesets->setData( QVariant( true), Qt::UserRole+4);
  36.  
  37. Sounds->setEditable( false);
  38. Sounds->setData( QVariant(Resource_Sound), Qt::UserRole+1);
  39. Sounds->setData( QVariant( -1), Qt::UserRole+2);
  40. Sounds->setData( QVariant( true), Qt::UserRole+3);
  41. Sounds->setData( QVariant( true), Qt::UserRole+4);
  42.  
  43. Objects->setEditable( false);
  44. Objects->setData( QVariant(Resource_Object), Qt::UserRole+1);
  45. Objects->setData( QVariant( -1), Qt::UserRole+2);
  46. Objects->setData( QVariant( true), Qt::UserRole+3);
  47. Objects->setData( QVariant( true), Qt::UserRole+4);
  48.  
  49. CollisionMasks->setEditable( false);
  50. CollisionMasks->setData( QVariant(Resource_Collision_Mask), Qt::UserRole+1);
  51. CollisionMasks->setData( QVariant( -1), Qt::UserRole+2);
  52. CollisionMasks->setData( QVariant( true), Qt::UserRole+3);
  53. CollisionMasks->setData( QVariant( true), Qt::UserRole+4);
  54.  
  55. Markers->setEditable( false);
  56. Markers->setData( QVariant(Resource_Marker), Qt::UserRole+1);
  57. Markers->setData( QVariant( -1), Qt::UserRole+2);
  58. Markers->setData( QVariant( true), Qt::UserRole+3);
  59. Markers->setData( QVariant( true), Qt::UserRole+4);
  60.  
  61. Maps->setEditable( false);
  62. Maps->setData( QVariant(Resource_Map), Qt::UserRole+1);
  63. Maps->setData( QVariant( -1), Qt::UserRole+2);
  64. Maps->setData( QVariant( true), Qt::UserRole+3);
  65. Maps->setData( QVariant( true), Qt::UserRole+4);
  66.  
  67. root->appendRow( Sprites);
  68. root->appendRow( Backgrounds);
  69. root->appendRow( Tilesets);
  70. root->appendRow( Sounds);
  71. root->appendRow( Objects);
  72. root->appendRow( CollisionMasks);
  73. root->appendRow( Markers);
  74. root->appendRow( Maps);
  75. }
  76.  
  77. sprCount = bgCount = tlsCount = sndCount = objCount = collisionMaskCount = markerCount = mapCount = 0;
  78. }
  79.  
  80. Qt::ItemFlags ResourceModel::flags(const QModelIndex &index) const
  81. {
  82. Qt::ItemFlags flags = QStandardItemModel::flags( index);
  83.  
  84. if (!index.isValid())
  85. return flags;
  86.  
  87. if (!index.data( Qt::UserRole+4).toBool())
  88. {
  89. flags |= Qt::ItemIsDragEnabled;
  90. }
  91.  
  92. if (index.data( Qt::UserRole+3).toBool())
  93. {
  94. flags |= Qt::ItemIsDropEnabled;
  95. }
  96.  
  97. return flags;
  98. }
  99.  
  100. QStringList ResourceModel::mimeTypes()
  101. {
  102. list << "resource/index";
  103. return list;
  104. }
  105.  
  106. QMimeData *ResourceModel::mimeData(const QModelIndexList &indexes) const
  107. {
  108. QMimeData *mimeData = new QMimeData();
  109. QByteArray encodedData;
  110.  
  111. QDataStream stream(&encodedData, QIODevice::WriteOnly);
  112.  
  113. foreach (const QModelIndex &index, indexes)
  114. {
  115. if (index.isValid())
  116. {
  117. stream << index.data( Qt::UserRole+1);
  118. itemFromIndex( index)->write( stream);
  119. }
  120. }
  121.  
  122. mimeData->setData("resource/index", encodedData);
  123. return mimeData;
  124. }
  125.  
  126. bool ResourceModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
  127. {
  128. QByteArray encodedData = data->data("resource/index");
  129. QDataStream stream(&encodedData, QIODevice::ReadOnly);
  130.  
  131. if (action == Qt::IgnoreAction)
  132. return true;
  133.  
  134. if (encodedData.isEmpty())
  135. return false;
  136.  
  137. int type;
  138. stream >> type;
  139.  
  140. if (!data->hasFormat("resource/index") && ( type != parent.data( Qt::UserRole+1).toInt()))
  141. return false;
  142.  
  143. if (column > 0)
  144. return false;
  145.  
  146. int beginRow;
  147.  
  148. if (row != -1)
  149. beginRow = row;
  150. else if (parent.isValid())
  151. beginRow = parent.row();
  152. else
  153. beginRow = rowCount(QModelIndex());
  154.  
  155. item->read( stream);
  156.  
  157. insertRow( beginRow, item);
  158.  
  159. return true;
  160. }
To copy to clipboard, switch view to plain text mode