2014-11-08 48 views
0

我正在寫一個對象到QML的序列化,並希望能夠獲得在QML對象中定義的函數的源代碼。假設我有在QML(test.qml)下面的例子:如何在C++中獲取QML方法的源代碼?

​​

我創建一個QObject:從obj

有什麼辦法(可哈克),以獲得obj的方法foo的源代碼,而無需解析QML文件obj從被創造?

可以使用QQmlComponentobj是從任何其他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了。

+0

你想要一個源代碼?或者只是想運行功能? – nitish005 2014-11-08 05:12:45

+0

我需要的源代碼,而不是運行該功能。 – Xilexio 2014-11-08 15:44:27

回答

1

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

但是,它可以使用QML解析器檢索。壞消息是QML解析器是Qt私有API的一部分,因此在使用不同的Qt庫構建時可能無法正常工作。

使用Qt 5.3解析QML的代碼。0私人API或多或少:

.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

0

我也沒有找到任何方式來這樣做。但我找到了解決辦法。

reffer this firts

現在,正如你knwo我們可以在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())); 

這裏我們使用的屬性更改事件「稱之爲」調用myFunction的()

+0

我需要源代碼,而不是運行該功能的方法。另外,爲了運行這個函數,我提供的代碼片段也可以正常工作:'''''QQmlExpression expr(engine.rootContext(),obj,「foo()」);'。 – Xilexio 2014-11-08 15:47:33