Я думаю, что нашел решение, которое более или менее соответствует тому, что я ожидал от Framework.
Заголовочный файл:
class QextDragDropModel : public QStandardItemModel
{
public:
/**
* Uses the passed indexes, and encodes a list of QStandardItem pointers into
* the mime data.
*/
virtual QMimeData* mimeData(const QModelIndexList &indexes) const;
/**
* Decodes the mimedata, and uses the each QStandardItem::clone() implmentation
* to place a copy at the requested position of the model. If it is a move
* operation Qt will remove the previous item.
*/
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent);
};
Внедрение:
QMimeData* QextDragDropModel::mimeData(const QModelIndexList &indexes) const
{
// Need to have the base function create the initial mimeData.
// It apparently puts something in there that makes Qt call dropMimeData().
QMimeData* mimeData = QStandardItemModel::mimeData(indexes);
// The raw data that will be placed in the mimeData.
QByteArray mimeBytes;
// Scope the data stream.
{
QDataStream ds(&mimeBytes, QIODevice::WriteOnly);
// The first item encoded will be the number of pointers to expect.
ds << quint32(indexes.size());
// Now for each index get a pointer to the standardItem, and write
// itto the datastream.
for (int i = 0; i < indexes.size(); i++)
{
QStandardItem* ptrItem = itemFromIndex(indexes[i]);
ds.writeRawData((const char*)&ptrItem, sizeof(QStandardItem*));
}
}
// Add the encoded standard item pointers into the mimeData.
mimeData->setData("Qt/QStandardItemArray", mimeBytes);
return mimeData;
}
bool QextDragDropModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent)
{
// Get the QStandardItem target of the drop.
QStandardItem* target = itemFromIndex(parent);
// If the target is valid, accepts drops and the mimedata has QStandardItem pointers
// go ahead with decode and insertion. (Checking drop enabled pobably already
// done by the framework before calling this function.)
if ( NULL != target && target->isDropEnabled() && data->hasFormat("Qt/QStandardItemArray") )
{
// Fetch the encoded bytes, create a data stream for decoding,
// and variables to store the output.
QByteArray indexListBytes = data->data("Qt/QStandardItemArray");
QDataStream ds(&indexListBytes, QIODevice::ReadOnly);
quint32 numItems = 0;
// Get the number of items, allocate memory to store pointers to
// them and read the pointer data into that memory.
ds >> numItems;
int byteLen = numItems*sizeof(QStandardItem*);
QStandardItem** stdItems = (QStandardItem**)malloc(byteLen);
ds.readRawData((char*)stdItems, byteLen);
// Add items to the target at a specific child index if requested,
// using thier clone() function to create the items.
for (int i = 0; i < numItems; i++)
{
if ( 0 <= row )
target->insertRow(row, stdItems[i]->clone());
else
target->appendRow(stdItems[i]->clone());
}
// Free memory allocated to store item pointers.
free(stdItems);
return true;
}
return false;
}
Для моего приложения я, вероятно, добавлю собственный класс элементов с функциональностью, позволяющей принимать или отклонять конкретные элементы, при этом модель запрашивает это вместо простого сброса во что-либо, которое принимает отбрасывания, но для основного вопроса это хорошо.