如何在C ++中获取QML方法的源代码?

时间:2014-11-08 03:27:06

标签: javascript c++ qt qml qt5

我正在将对象的序列化写入QML,并希望能够获得QML对象中定义的函数的源代码。假设我在QML中有以下示例(test.qml):

import QtQml 2.2

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

我从中创建了QObjectobj

有没有办法(可能是hacky)获取obj方法foo的源代码而不解析QML文件obj是从吗

可以使用QQmlComponent obj从任何其他Qt类创建,只要我不必自己解析它。或者,如何在不编写自己的解析器的情况下从test.qml文件中获取函数的源代码?我不想对test.qml采取任何特别的措辞(例如,它可能与上面的不同,并且它不必足够简单以使用正则表达式或其他不完整的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了。

2 个答案:

答案 0 :(得分:2)

我认为从已经创建的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的更多方法。

答案 1 :(得分:0)

我也没有找到任何办法。但我找到了解决办法。

reffer this 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()));

这里我们正在使用属性的变更事件&#39; call&#39;调用myFunction()