如何在Qt中使用C++获取剪贴板中的MIME类型和数据。

huangapple go评论81阅读模式
英文:

How to get MIME Type and data stored in clipboard in qt with c++

问题

我想要获取剪贴板中存储的 MIME 类型和数据,并通过网络传输到另一台设备,但似乎 Qt 没有提供直接的方法来实现这一点。如何完成这个任务?

我已经看过 QClipboardQMimeData,但它们没有提供一种获取剪贴板的 MIME 类型的方法,但它们有各种 has* 方法。我可以构建文本、HTML、URL 的 MIME 类型,但对于图像,我不能做同样的事情,因为有各种类型的图像,如 png 和 jpeg,那么我如何从 QT API 中获取 MIME 类型呢?

#include <QApplication>
#include <QClipboard>
#include <QMimeData>

int main(int argc, char** argv) {
  auto application = QApplication(argc, argv);
  auto clip = QApplication::clipboard();

  const auto onChange = [&]() {
    const auto mimeData = clip->mimeData();
    // 我不能仅使用 has* 方法,因为
    // 如果它是图像,有各种
    // 图像类型,如 png、jpg 等。
    const auto mimetype = "如何获取";
    const auto data = mimeData->data(mimetype);
  };

  auto signal = &QClipboard::changed;
  QObject::connect(clip, signal, onChange);
  application.exec();
}
英文:

I want to get the Mime Type and data stored in a clipboard and transfer it via network to another device but it seems like Qt doesn't provide a Straightforward way to do it, How to accomplish this ?

I have seen the QClipboard and QMimeData but it doesn't provide a way to get the mime type of the clipboard but it has various has* methods. I can construct the mime type for text, HTML, Url. But I can't do the same for images because there are various types of images like png, and jpeg so how can I get the mime type from the QT API?

#include &lt;QApplication&gt;
#include &lt;QClipboard&gt;
#include &lt;QMimeData&gt;

int main(int argc, char** argv) {
  auto application = QApplication(argc, argv);
  auto clip = QApplication::clipboard();

  const auto onChange = [&amp;]() {
    const auto mimeData = clip-&gt;mimeData();
    // I can&#39;t just use has* method because
    // if it is a image there are various
    // type of image like png, jpg, etc.
    const auto mimetype = &quot;How to Get&quot;;
    const auto data = mimeData-&gt;data(mimetype);
  };

  auto signal = &amp;QClipboard::changed;
  QObject::connect(clip, signal, onChange);
  application.exec();
}

答案1

得分: 2

以下是翻译好的内容:

每当有东西被复制到剪贴板时,可能同时复制多个数据片段到剪贴板上。例如,如果你从浏览器复制选定的文本,它可能将数据同时复制为 text/htmltext/plain。如果你将这些数据粘贴到只能理解 text/plain 的简单文本编辑器(例如Windows记事本)中,它将粘贴 text/plain 数据并忽略 text/html 数据。但如果你将数据粘贴到支持富文本编辑的进程中(例如LibreOffice Writer、Microsoft Word等),那么它们将粘贴 text/html 数据以保留格式。

这意味着剪贴板中很少只有一个数据片段,而通常有多个数据片段。

你需要做的是:

  • 遍历所有 data->formats() 并获取该格式的 data->data(...)
  • 对所有数据进行序列化并通过网络传输。
  • 在网络的另一端,使用提供的所有格式来填充剪贴板。

我稍微调整了你的代码:

#include <QApplication>
#include <QClipboard>
#include <QMimeData>
#include <QVector>
#include <QString>
#include <QByteArray>
#include <QDebug>

#include <memory>

static QVector<QPair<QString, QByteArray>> serializeMimeData(QMimeData const* data)
{
    QVector<QPair<QString, QByteArray>> result;
    if (data) {
        const auto formats = data->formats();
        result.reserve(formats.size());
        for (QString const& format : formats)
            result.push_back(qMakePair(format, data->data(format)));
    }
    return result;
}

static QMimeData* unserializeMimeData(QVector<QPair<QString, QByteArray>> const& data)
{
    if (!data.size())
        return nullptr;

    auto result = std::make_unique<QMimeData>();
    for (auto const& formatAndData : data)
        result->setData(formatAndData.first, formatAndData.second);
    const auto formats = result->formats();
    return result.release();
}

int main(int argc, char** argv) {
  auto application = QApplication(argc, argv);
  auto clip = QApplication::clipboard();

  const auto onChange = [&]() {
    const auto mimeData = clip->mimeData();
    const auto data = serializeMimeData(mimeData);
    
    // 将数据传输到其他系统

    // 在其他系统上
    QSignalBlocker block(clip);
    auto newMimeData = unserializeMimeData(data);
    clip->clear();
    if (newMimeData)
        clip->setMimeData(newMimeData);
  };

  auto signal = &QClipboard::changed;
  QObject::connect(clip, signal, onChange);
  application.exec();
}

该代码目前没有实际用途,因为它会在任何内容更改时都替换剪贴板内容为相同的值。但它展示了方程的两边。

请注意,我在这里假设你在另一侧也将使用Qt - 你不必这样做,如果你知道如何通过其他方式与另一系统的剪贴板交互,可以使用其他方法。我还使用了一个简单的 QVector<QPair<QString, QByteArray>> 作为此简单示例的序列化格式 - 当通过网络发送数据时,你需要自己找出适合的格式。

还有一些剪贴板工作的细节可能没有在这里处理,但希望这给你一个良好的起点。

英文:

Whenever something is copied to a clipboard, multiple pieces of data may be copied to the clipboard at the same time. For example, if you copy selected text from a browser, it may copy the data as both text/html and text/plain. If you paste the data in a simple text editor (such as Windows Notepad) that only understands text/plain, it will paste that data and ignore the text/html data. But if you paste the data into a process that supports rich text editing (e.g. LibreOffice Writer, Microsoft Word, etc.), then those will paste the text/html data to preserve formatting.

This means that there is rarely only ever a single piece of data in the clipboard, but multiple pieces of data.

What you'd need to do would be the following:

  • Iterate through all data-&gt;formats() and get data-&gt;data(...) for that format.
  • Serialize all of that and transmit it over the network.
  • On the other side of the network fill the clipboard with all of the formats that have been provided.

I've adjusted your code a bit:

#include &lt;QApplication&gt;
#include &lt;QClipboard&gt;
#include &lt;QMimeData&gt;
#include &lt;QVector&gt;
#include &lt;QString&gt;
#include &lt;QByteArray&gt;
#include &lt;QDebug&gt;

#include &lt;memory&gt;

static QVector&lt;QPair&lt;QString, QByteArray&gt;&gt; serializeMimeData(QMimeData const* data)
{
    QVector&lt;QPair&lt;QString, QByteArray&gt;&gt; result;
    if (data) {
        const auto formats = data-&gt;formats();
        result.reserve(formats.size());
        for (QString const&amp; format : formats)
            result.push_back(qMakePair(format, data-&gt;data(format)));
    }
    return result;
}

static QMimeData* unserializeMimeData(QVector&lt;QPair&lt;QString, QByteArray&gt;&gt; const&amp; data)
{
    if (!data.size())
        return nullptr;

    auto result = std::make_unique&lt;QMimeData&gt;();
    for (auto const&amp; formatAndData : data)
        result-&gt;setData(formatAndData.first, formatAndData.second);
    const auto formats = result-&gt;formats();
    return result.release();
}


int main(int argc, char** argv) {
  auto application = QApplication(argc, argv);
  auto clip = QApplication::clipboard();

  const auto onChange = [&amp;]() {
    const auto mimeData = clip-&gt;mimeData();
    const auto data = serializeMimeData(mimeData);
    
    // Transfer stuff to other system

    // on other system
    QSignalBlocker block(clip);
    auto newMimeData = unserializeMimeData(data);
    clip-&gt;clear();
    if (newMimeData)
        clip-&gt;setMimeData(newMimeData);
  };

  auto signal = &amp;QClipboard::changed;
  QObject::connect(clip, signal, onChange);
  application.exec();
}

The code currently does nothing useful, because it replaces the clipboard contents with the same value any time something changes. However it shows you both sides of the equation.

Note that I've assumed here that you'd be using Qt on the other side too - you don't have do do that, if you know how to talk to the clipboard on the other system via some other means, you can use that instead. I've also used a simple QVector&lt;QPair&lt;QString,QByteArray&gt;&gt; as the serialization format for this simple example - when sending the data over the network you'd have to figure that out for yourself.

There may also be some subtleties of how clipboards work that aren't handled by this, but hopefully this gives you a good starting point.

huangapple
  • 本文由 发表于 2023年7月10日 21:34:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76654283.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定