LtWorf LtWorf - 1 year ago 75
C++ Question

Passing QClipboard to QML

I am trying to make the clipboard available to some QML code.

Passing the clipboard object seems to work, but then I can't call its methods.

Here's an example of a QClipboard working fine in C++, being passed to QML, and in the debug output it still being a QClipboard object but losing its functions.

main.cpp

#include <QApplication>
#include <QClipboard>
#include <QQmlApplicationEngine>
#include <qqmlcontext.h>
#include <QtQml>


int main(int argc, char *argv[]) {
QApplication app(argc, argv);

QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("clipboard", QApplication::clipboard());
qDebug() << QApplication::clipboard()->text(); // This correctly prints the copied text
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}


main.qml

import QtQuick 2.5
import QtQuick.Controls 1.3
ApplicationWindow {
visible: true
MouseArea {
acceptedButtons: Qt.MiddleButton
anchors.fill: parent
onClicked: {
console.log(clipboard)
console.log(clipboard.getText())
}
}
}


qml.qrc

<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>


test.pro

TEMPLATE = app
VERSION = 1.0

QT += qml widgets gui
QMAKE_LFLAGS += -Wl,--as-needed

SOURCES += main.cpp
RESOURCES += qml.qrc

Answer Source

QObject's functions need to be slots if you want to call them from QML. QClipboard declares no slots, so you can't call its functions directly. You can create a proxy, though:

qclipboardproxy.hpp

#ifndef QCLIPBOARDPROXY_HPP
#define QCLIPBOARDPROXY_HPP

#include <QObject>

class QClipboard;

class QClipboardProxy : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString text READ text NOTIFY textChanged)
public:
    explicit QClipboardProxy(QClipboard*);

    QString text() const;

signals:
    void textChanged();

private:
    QClipboard* clipboard;
};

#endif // QCLIPBOARDPROXY_HPP

qclipboardproxy.cpp

#include "qclipboardproxy.hpp"

#include <QClipboard>

QClipboardProxy::QClipboardProxy(QClipboard* c) : clipboard(c)
{
    connect(c, &QClipboard::dataChanged, this, QClipboardProxy::textChanged)
}

QString QClipboardProxy::text()
{
    return clipboard->text();
}

and in

main.cpp

engine.rootContext()->setContextProperty("clipboard",
    new QClipboardProxy(QGuiApplication::clipboard()));

Now you can call:

console.log(clipboard.text)

or even

someProperty: clipboard.text