0%

【Linux技术分享】利用QT的clipboard库监听和设置剪切板

利用QT的clipboard库监听和设置剪切板

使用QT的Clipboard库,监听和设置uos剪切板变化。经过dbus接口,把uos的剪切板暴露出来,从而进行设置和监听

dbus的创建

  1. 在C++头文件定义Q_SLOTS,和Q_SIGNALS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Clipboard : public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "com.deepin.ListenClipboard")

public:
explicit Clipboard(QObject *parent = nullptr);

public Q_SLOTS:
void SetDataToCB(const QString &clipboardData, const int nType);

Q_SIGNALS:
void ClipboardChanged(const QString &pathlist, const int nType);
}
  1. 创建导出dbus接口的xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="com.deepin.ListenClipboard">
<signal name="ClipboardChanged">
<arg name="str" type="s" direction="out"/>
<arg name="nType" type="i" direction="out"/>
</signal>
<method name="SetClipboardData">
<arg name="str" type="s" direction="in"/>
<arg name="nType" type="i" direction="in"/>
</method>
</interface>
</node>
  1. 使用工具生成适配器类

qdbusxml2cpp com.deepin.ListenClipboard.xml -i com.deepin.ListenClipboard.xml -a widgetadaptor

  1. 安装适配器将Widget类中的方法导出DemoAdaptor adaptor(&w);

剪切板监听

  1. 调用connect,把自己的funccilpboard变化连接一起
    1
    2
    3
    4
    void Clipboard::CheckDataToCb()
    {
    connect(m_clipBoard, &QClipboard::dataChanged, this, &Clipboard::ListenDataToCB);
    }
  2. 获取文件图片和文字
  • 图片

    1
    2
    3
    4
    5
    6
    QImage img = qvariant_cast<QImage>(strMimeData->imageData());
    QByteArray imageArray;
    QBuffer buffer;
    buffer.open(QIODevice::WriteOnly);
    img.save(&buffer, "PNG");
    imageArray.append(buffer.data());
  • 文字

    1
    2
    QString strText = strMimeData->text();
    qDebug() << "clipboard text received:" << strText;
  • 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    QString strFileList;
    QList<QUrl> cbUrls = strMimeData->urls();

    for (int i = 0; i < cbUrls.size(); i++) {
    QString strFile = cbUrls.at(i).toLocalFile();
    if (isFusePath(strFile) || 0 == strFile.size()) {
    continue;
    }
    strFileList += strFile + "\n&t"; // windows约定文件路径分隔符
    }
    qDebug() << "clipboard file received:" << strFileList;
  1. 发送数据至Q_SIGNALS

    1
    emit ClipboardChanged(strClipboardData,static_cast<int>(nType));

    剪贴板设置

  2. 使用dbus绑定接口SetDataToCB

    1
    QMetaObject::invokeMethod(parent(), "SetDataToCB", Q_ARG(QString, path),Q_ARG(const int,nType));
  3. 设置文件图片和文字

  • 图片

    1
    2
    3
    4
    5
    QImage img;
    QByteArray arr_base64 = clipboardData.toLatin1();
    img.loadFromData(QByteArray::fromBase64(arr_base64));
    m_clipBoard->setImage(img);
    qDebug() << "set clipboard data as Image";
  • 文字

    1
    2
    m_clipBoard->setText(clipboardData);
    qDebug() << "set clipboard data as text:" << clipboardData;
  • 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    QString CopiedFile;
    QString UrlList;
    qDebug() << "set clipboard data as file:" << clipboardData;
    QStringList clipboardList = clipboardData.split("\n");
    for (QString path : clipboardList) {
    if (!path.isEmpty()) {
    CopiedFile = CopiedFile + "copy\nfile://" + path;
    UrlList = UrlList + "file://" + path + "\n";
    }
    }
    if (CopiedFile.size() == 0) {
    qDebug() << "clipboard path is empty";
    return;
    }
    QMimeData *newMimeData = new QMimeData();
    newMimeData->setData("x-special/gnome-copied-files",
    QByteArray(CopiedFile.toStdString().c_str()));
    newMimeData->setData("text/uri-list", QByteArray(UrlList.toStdString().c_str()));
    m_clipBoard->clear();
    m_clipBoard->setMimeData(newMimeData);