簡體   English   中英

如何在C ++中獲取QML方法的源代碼?

[英]How to get source code of a QML method in C++?

我正在將對象序列化為QML,並希望能夠獲取QML對象中定義的函數的源代碼。 假設我在QML( test.qml )中有以下示例:

import QtQml 2.2

QtObject {
    function foo() {
        return 42;
    }
}

我從中創建了一個QObjectobj

是否有任何方法(可能是駭客的)在不解析創建obj的QML文件的情況下獲取obj方法foo的源代碼?

沒關系使用QQmlComponent obj從或任何其他Qt類創建的,只要我沒有分析它自己。 或者,如何在不編寫自己的解析器的情況下從test.qml文件獲取函數的源代碼? 我不想承擔關於test.qml任何特殊test.qml (例如,它可以與上面的代碼不同,並且不必使用regexp或其他不完整的QML解析器就足夠簡單)。

假設它像JavaScript一樣工作,我嘗試了類似的方法:

QQmlExpression expr(engine.rootContext(), obj, "foo.toString()");
QVariant sourceCode = expr.evaluate();

但是,它不起作用。

編輯:根據http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.2 ,功能對象原型的toString方法是實現定義的。 對於QML,我得到的結果是:

QVariant(QString, "function() { [code] }")

由於似乎沒有辦法通過JS或C ++獲取代碼,因此我不再將自己局限於公共Qt API。

我認為不可能從已經創建的QML對象中獲取函數的源代碼。 它似乎沒有任何C ++接口,JavaScript也不使用toSource方法返回它。

但是,可以使用QML解析器進行檢索。 壞消息是QML解析器是Qt私有API的一部分,因此當使用不同的Qt庫版本時,它可能不起作用。

使用Qt 5.3.0私有API解析QML的代碼或多或少:

.pro文件:

QT += qml qml-private

cpp文件:

using namespace QQmlJS::AST;

class LVisitor: public QQmlJS::AST::Visitor {
public:
    LVisitor(QString code): _code(code) {}

    virtual bool visit(FunctionBody *fb) {
        qDebug() << "Visiting FunctionBody" <<
                    printable(fb->firstSourceLocation(), fb->lastSourceLocation());
        return true;
    }

private:
    QStringRef printable(const SourceLocation &start, const SourceLocation &end) {
        return QStringRef(&_code, start.offset, end.offset + end.length - start.offset);
    }

private:
    QString _code;
};

void testQmlParser() {
    QFile file(":/test.qml");
    file.open(QFile::ReadOnly);
    QString code = file.readAll();
    file.close();

    QQmlJS::Engine engine;
    QQmlJS::Lexer lexer(&engine);

    lexer.setCode(code, 1, true);

    QQmlJS::Parser parser(&engine);

    if (!parser.parse() || !parser.diagnosticMessages().isEmpty()) {
        foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
            qDebug() << "Parse" << (m.isWarning() ? "warning" : "error") << m.message;
        }
    }

    UiProgram *ast = parser.ast();

    LVisitor visitor(code);
    ast->accept(&visitor);
}

若要獲取有關定義函數的對象的更精確信息,或僅從AST獲得更多信息,請實現QQmlJS::AST::Visitor更多方法。

我也沒有找到任何辦法。 但我找到了解決方法。

reffer firts

現在,當您知道我們可以使用C ++訪問QML對象時。 將執行以下操作以在QML中運行該功能。

Item {
    width: 100; height: 100

    Rectangle {
        property bool call:true

        objectName: "rect"
        onCallChanged()
        {
             myFunction();
        }
        function myFunction()
        {
             //your code
        }
    }
}

在C ++中,您必須執行以下操作:

QObject *rect = object->findChild<QObject*>("rect");
if (rect)
    rect->setProperty("call", !(rect->property("call").toBool()));

這里我們使用屬性'call'的change事件來調用myFunction()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM