QML の文法メモ

Qt で使われている QML という独自言語を読み書きしないといけないことになったのでメモ。QML は非常に読みやすく優れた言語だと思うが、自分で書く段になると相当かなり文法が複雑で、はて??? となってしまったので引っかかった点を書く。

サンプル

```qml
import QtQuick 2.6
import QtQuick.Window 2.2

Window {
    visible: true
    width: 800
    height: 600
    property string prompt: "Your input> "
    Component.onCompleted: console.log("Completed Running!")

    Rectangle {
        width: 100
        height: 100

        gradient: Gradient {
            GradientStop { position: 0.0; color: "yellow" }
            GradientStop { position: 1.0; color: "green" }
        }
    }

    Rectangle {
        x: 200
        width: 100
        height: 100

        gradient: Gradient {
            stops: [
                GradientStop { position: 0.0; color: "green" },
                GradientStop { position: 1.0; color: "yellow" }]
        }
    }

    TextInput {
        y: 200
        id: myTextInput
        text: "Hello World"
        onTextChanged: console.log("Text is changed:", text)
    }

    Text {
        y: 300
        text: prompt + myTextInput.text
        font { pixelSize: 30 }
        font.bold: true
        // font: Font { pixelSize: 30; bold: true }
    }

    Text1 {
        y: 400

        Text { text: "First item" }
        Text { text: "Second item" }
        Text { text: "Third item" }
    }

    TextList {
        y: 500

        Text { text: "First item" }
        Text { text: "Second item" }
        Text { text: "Third item" }
    }
}
```

* QML は、一つ以上の import 宣言の後ろに一つのオブジェクト宣言を置く。
* オブジェクト `クラス { 属性: 値; 属性: 値; }` のように書く。CSS に似ている。改行の前のセミコロンは省略出来る。
* 属性の値として、数値、文字列の他にオブジェクトを置ける。例: Rectangle の中の gradient 属性
* オブジェクト宣言の中に属性名を書かないで別のオブジェクト宣言を書くと、子オブジェクトになる。(default properties)
    * 例: Window の中の Rectangle
    * 例: Gradient の中の GradientStop

## [属性](http://doc.qt.io/qt-5/qtqml-syntax-objectattributes.html)

属性には以下の種類がある。

* id: オブジェクトに付けた名前。他のオブジェクトから参照出来る。
    * id はスコープの中で一意である。
    * 例: TextInput に myTextInput という名前を付けている。 Text 内の text が参照している。
* プロパティ属性: 様々な値を入れる所。
    * オブジェクトに最初からあるプロパティ属性の他、C++ や property 宣言でカスタムプロパティを追加出来る。
        * 例: Window に prompt というカスタムプロパティを作り、Text 内で参照している。
    * プロパティ属性には、on(プロパティ名)Changed というシグナルが自動的に出来る。
        * 例: TextInput の text を変更すると onTextChanged が呼ばれる。
    * プロパティの値に書けるもの
        * 静的な値。数値、文字列、色々な QML Type。
        * 束縛表現。Javascript 式。Javascript 式が参照する値が変更された時に自動的に式を評価して代入する。
            * Javascript の代入式で束縛表現を使いたい場合 Qt.binding を使う。
                例: height = Qt.binding(function() { return width * 3 })
    * プロパティのグループ記法
        * プロパティの中にプロパティがある場合、`親プロパティ.子プロパティ: 値` の形で中のプロパティの値を定義出来る。
            * 例: font.bold: true
        * 別記法として、`親プロパティ {子プロパティ: 値}` でも良い。
            * 例: `font { pixelSize: 30 }`
        * これは意味的には `font: Font { pixelSize: 30; bold: true }` 同じはずだが Element is not creatable. のエラーになる。
* メソッド属性
    * オブジェクト内に書いた javascript function 定義はメソッドになる。
* [Attached Properties](http://doc.qt.io/qt-5/qtqml-syntax-objectattributes.html#attached-properties-and-attached-signal-handlers)
    * これは不思議な機能だ。オブジェクトに元々存在しないプロパティやシグナルハンドラを他のクラスを使って追加出来る。
        * 例: Component.onCompleted は対象のオブジェクト (Window) の描画が完了すると呼ばれる。
    * [Attached Properties の実装](http://doc.qt.io/qt-5/qtqml-cppintegration-definetypes.html#providing-attached-objects-for-data-annotations)

## [Default Propaties](http://doc.qt.io/qt-5/qtqml-syntax-objectattributes.html#default-properties)

QML には親子関係が簡単に書ける Default Properties という機能があるが、結構複雑だ。以下例を挙げる。

```qml
// Text1.qml
import QtQuick 2.0

Text {
    default property Text someText

    text: "The Text1 has: " + someText.text
}
```

```qml
// TextList.qml
import QtQuick 2.0

Text {
    default property list<Text> textList

    onTextListChanged: {
        text = "The TextList has: ";
        for (var i = 0; i < textList.length; i++) {
            text += textList[i].text + " and ";
        }
    }
}
```

* オブジェクト宣言の中に、属性名を書かないでそのまま子要素としてオブジェクトを置くと default property に格納される。
* オブジェクトは default property を一つだけ持つ。
* default property が list の時は、子要素は全て default property に格納される。
    * 例: TextList は list<Text> 側の default property を持つ。全ての子要素が textList に格納される。
* default property が list でない時は、最後の要素だけ default property に格納される。
    * 例: Text1 は Text 型の default property を持つ。最後の子要素が someText に格納される。


## C++ との連携

あとで

## 参考
* [Defining QML Types from C++](http://doc.qt.io/qt-5/qtqml-cppintegration-definetypes.html)
* [Scope and Naming Resolution](http://doc.qt.io/qt-5/qtqml-documents-scope.html)
* [Qt QML](http://doc.qt.io/qt-5/qtqml-index.html)
* [QML JS Grammer](http://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/qml/parser/qqmljs.g)