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 <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();
// I can't just use has* method because
// if it is a image there are various
// type of image like png, jpg, etc.
const auto mimetype = "How to Get";
const auto data = mimeData->data(mimetype);
};
auto signal = &QClipboard::changed;
QObject::connect(clip, signal, onChange);
application.exec();
}
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:
data->formats()
and get data->data(...)
for that format.I've adjusted your code a bit:
#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);
// Transfer stuff to other system
// on other system
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();
}
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<QPair<QString,QByteArray>>
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.