如何为自定义 MIME 类型实现剪贴板操作?

How to implement clipboard actions for custom mime-types?

我正在尝试在复杂的应用程序中实施 copy/cut/paste。
我有一个 QGraphicsScene,它可以包含 QGraphicsItem 个不同子类型的子类型,相当复杂(Item 作为第二个父级存储自定义属性)。
我会 copy/cut 选择项目,然后将它们粘贴回原位。
我已经使用本地版本实现了它:项目列表。

void copyItemsActionOld()
{
    foreach(QGraphicsItem* qItem, selectedItems())
    {
        Item* newItem = (dynamic_cast<Item*>(qItem))->createItemCopy();
        m_itemClipboard.append(newItem);
    }
}

粘贴时,我复制了剪贴板中的所有项目并将它们添加到场景中。就这么简单......

但是

我需要使用全局系统剪贴板实现它。

我看到创建自定义 MIME 类型就像在 QMimeData 对象上调用 setData 一样简单,在我组成格式名称之后......(我希望这是真的)

static const QString _mimeType("application/myItem");
void copyItemsAction()
{
    QMimeData* _mimeData = new QMimeData;
2    QByteArray _itemData = ?????;
    _mimeData->setData(_mimeType, _itemData);
    QClipboard* _clipboard = QApplication::clipboard();
    _clipboard->clear();
    _clipboard->setMimeData(_mimeData);
}

void pasteItemsAction()
{
    QClipboard* _clipboard = QApplication::clipboard();
    const QMimeData* _mimeData = _clipboard->mimeData();

    QStringList _formats = _mimeData->formats();
    foreach (QString _format, _formats)
    {
        if (_format == _mimeType)
        {
            QByteArray _itemData = _mimeData->data(_mimeType);
3           // then do what ? How do I parse it ?
        }
    }
}

我的问题

1) copyItemsActionpasteItemsAction 的上述片段是否接近剪贴板操作的工作方式?

2) 如何将项目数据放入 QByteArray ?

3) 如何解析 QByteArray 中的数据?

4) 我是否需要在其他任何地方注册自定义 MIME 类型? (除了我刚刚在我的两个功能中所做的);它会是多平台的吗?

我已经为所有项目实现了 saveload 功能。像...

void Item::saveItem(QDataStream &outFile)
{
    outFile << type;
    outFile << width;
    outFile << color.name();
}

我可以使用它来将项目数据放入 QByteArray 吗? (如何?)

我走在了正确的轨道上,我不断地向我的问题添加代码,直到我找到如何让它工作:

static const QString _mimeType("application/myItem");
void copyItemsAction()
{
    QByteArray _itemData;
    QDataStream outData(&_itemData, QIODevice::WriteOnly);
    outData << selectedItems().size();
    foreach(QGraphicsItem* qItem, selectedItems())
    {
        Item* item = dynamic_cast<Item*>(qItem);
        item->saveItem(outData);
    }

    QMimeData* _mimeData = new QMimeData;
    _mimeData->setData(_mimeType, _itemData);
    _mimeData->setText("My Items");
    QClipboard* _clipboard = QApplication::clipboard();
    _clipboard->clear();
    _clipboard->setMimeData(_mimeData);
}

void pasteItemsAction()
{
    QClipboard* _clipboard = QApplication::clipboard();
    const QMimeData* _mimeData = _clipboard->mimeData();

    QStringList _formats = _mimeData->formats();
    foreach (QString _format, _formats)
    {
        if (_format == _mimeType)
        {
            QByteArray _itemData = _mimeData->data(_mimeType);
            QDataStream inData(&_itemData, QIODevice::ReadOnly);
            int itemsSize;
            inData >> itemsSize;
            for (int i = 0; i < itemsSize; ++i)
            {
                Item* item = ...
                item->loadItem(inData);
            }
        }
    }
}

所以,对于问题 1,是的,我的方向是正确的;

对于问题 2 和 3 - 我能够使用 QDataStream 将信息 to/from 序列化为 QByteArray.
如果有更好/更有效/更快的方法,我很想知道...

对于问题 4 - 似乎我几乎可以使用任何字符串,如果我只想在我的应用程序的单个实例中 copy/paste。
如果我想在多个应用程序、我的应用程序的多个实例之间使用它,或者在 大多数 平台上进行拖放操作,也是如此。 (在我定位的嵌入式平台中,它似乎无法在多个 applications/instances 之间工作。)
警告 - 在 windows.

中打开另一个使用应用程序的剪贴板时,它经常失败