ジャンル不定の日記です。

QML勉強中(外部.jsの利用)

引き続き、QMLの勉強中。
.qmlファイル中にJavaScriptコード書いてクロスドメイン制約無しでXMLHttpRequestが使えることはわかったが、
設定画面はmain.qmlと別ファイルになるんで、JavaScriptは外部ファイルにして共有したほうが良さそう。
というわけで、.jsのimportをやってみた。


js.js
function HttpGet(url,cb){
    var http=new XMLHttpRequest();
    http.open("GET",url);
    http.onreadystatechange=function(){
        if(http.readyState==4){
            cb(http.responseText);
        }
    }
    http.send();
}
置き場所はmain.qmlと同じuiディレクトリ下にしたが、パス指定どころかURL指定でもimportできるようなんで都合のいい場所で良いぽい。
XMLHttpRequestでレスポンスを取得するfunctionだが、別ファイル化するのだから他も使えるように、.js側でUIの変更は行わずにコールバックで.qmlの方でUI変更を行う感じにした。


main.qml
import QtQuick 2.5
import QtQuick.Controls 1.4
import "js.js" as JavaScript
 
Column{
    property var url:"http://jvn.jp/rss/jvn.rdf"
    width:640
    height:480
    Text{
        id:tv
    }
    Button{
        text: "Button"
        onClicked:JavaScript.HttpGet("http://example.com/",function(res){tv.text=http.responseText;})
    }
    Component.onCompleted:JavaScript.HttpGet(url,function(res){tv.text=res;})
}
importのasで指定した名前がオブジェクトになって、その下にfunctionがある感じになる。
ファイル名のみを指定した場合はmain.qmlと同じディレクトリ、つまりui/js.jsをimportすることになるが、/を含めてでパス指定もできる。
2番目の引数でコールバックの無名関数を渡してmain.qml側でUI操作をするように改造した。


これで動いた。
というわけで、目的のFeedリーダーはもうすぐ作れそうだ。

QML勉強中(Plasmoidの設定)

引き続き、QMLの勉強中。
RSS等のニュース用Feedリーダーを作ろうとしているが、Feedアドレスの設定とかをPlasmoidの設定ボタンから行いたいが、今回はそれ。


Plasmoidの設定ボタンからのアクションを作るには、QTのリファレンス見ても書いて無いようで、KDEのリファレンス見ないとダメぽい。
KDEのリファレンスは発見するのも難しい状況なんだが、とりあえず動いた。


今までは、

metadata.desktop

contents/ui/main.qml
の2ファイルだけ作ってたが、新たに、
contents/config/config.qml
が必要。


config.qml
import org.kde.plasma.configuration 2.0

ConfigModel{
    ConfigCategory{
        name: "General"
        icon: "plasma"
        source: "main.qml"
    }
}
config.qml では、org.kde.plasma.configuration をimportして、
ConfigModelとConfigCategoryを定義すればいいぽい。

この config.qml を用意しておくと、Plasmoidの設定ボタンで設定画面が出てくるようになり、
[General]カテゴリに ui/main.qml で作ったUIが表示される。

今回はPlasmoidの設定ボタンのテスト目的なんで、設定用のUIは作らずに作成済みの main.qml を利用した。
実際には設定用の.qmlを用意して、JavaScriptのlocalStorageを利用して設定の保存と読み込みを行えば良いのかな?

あと、qmlsceneコマンドで.qmlを実行してもウインドウ表示されるだけでPlasmoidの設定ボタンは出てこないから、plasmapkg2コマンドでインストールする必要があるが、
plasmapkg2でインストールしちゃうとKDE再起動しないと再インストールが反映しなくなっちゃう。
config.qml のテストはqmlsceneでテストしておいて、全部完成してからplasmapkg2でインストールって感じにしないとダメだな。
最終的に一発勝負wこの仕様どうにかならんの?w


ここまでで得た知識で、目的の実現ができそうだな。
URLにジャンプするリンクの表示がまだか。TextにHTMLタグが使えるとか見た気がするが・・・

QML勉強中 (JavaScript連携編)

今日も引き続き、QMLの勉強中。
前回まででListViewを表示してJavaScriptで更新するのができたが、今回はクロスドメイン制約無しでXMLHttpRequestが使えるか?


main.qml
import QtQuick 2.5
import QtQuick.Controls 1.4
 
Column{
    width:640
    height:480
    Text{
        id:tv
    }
    Button{
        text: "Button"
        onClicked:(function(){
            var http=new XMLHttpRequest();
            http.open("GET","http://example.com");
            http.onreadystatechange=function(){
                if(http.readyState==4){
                    tv.text=http.responseText;
                }
            }
            http.send();
        })()
    }
}
TextとButtonを配置して、ボタンが押されたらXMLHttpRequestで取ってきたレスポンスを表示。
ドメイン制約はないようで、問題なくHTTP通信ができた。


Plasma5にして無くなった、ニュース見出しを表示するRSSリーダーの代わりを作ろうとしているんで、
あとはJavaScriptのコード書くだけでとりあえずできそう。

Plasma Widgetの設定ボタンから取ってくるFeedのアドレス設定とかできるようにしたいから、その辺ちょっと調べてみる。

QML勉強中 (JavaScript連携編)

引き続き、QMLの勉強中。
今回は、前回ListViewを表示してみたが、ListViewをJavaScriptで動的に更新してみる実験。

main.qml
import QtQuick 2.5
import QtQuick.Controls 1.4
 
Column{
    ListView{
        id:lv;
        ListModel{
            id:model
            ListElement{
                tx:"1"
            }
            ListElement{
                tx:"2"
            }
            ListElement{
                tx:"3"
            }
        }
        width:100
        height:200
        model:model
        delegate:Text{text:tx}
    }
    Button{
        text: "Button"
        onClicked:(function(){
            model.clear();
            model.append({"tx":"append1"});
            model.append({"tx":"append2"});
        })()
    }
}
前回は import QtQuick 2.0 としていたが、適切なバージョン番号がわからないのでAPIリファレンスのバージョン(最新?)に合わせることにした。
Arch Linux環境なので最新版がすぐ来るはずだし。
古い環境の場合はバージョン落とす必要があるかも。

今回はColumn型とButton型のオブジェクトを使用したが、Buttonを使うには QtQuick.Controls をimportする必要がある。

ボタンを押すとリストを更新する実験なんだが、
QMLの最上位にはオブジェクトは一個しか置けないぽくて、最上位にListViewとButtonを並べるのはダメみたい。
Column型は、子要素を縦方向に順番に並べてくれる。

ListViewは前回からちょっと省略した感じだが、ListViewには高さが無いのかな?
heightを指定しないとButtonと重なっちゃうようだったんでサイズ指定した。


Buttonは、onClickedでQMLのメソッドや自分で定義したJavaScriptのfunctionをクリック時に実行できる。
model.clear()でリストのデータを消去して、appendで新しく追加。
appendに渡す引数はJavaScriptのオブジェクト(ハッシュ)ぽい。

再利用もしない簡単な処理なんで無名関数を書いたが、当然だが名前付き関数を実行することもできる。
名前付きのfunctionを別の場所に定義する場合は、Button自身と親要素のColumn以外で定義した場合は id.func() の様にid指定で実行する必要がある。
ルート要素は一つしか置けないようで、Columnの外側には別のオブジェクトを置くこともできないし、JavaScriptのfunctionを置くこともできないぽい。
複数オブジェクトで同じfunctionを利用するような場合は、.jsを別ファイルにしてimportした方が自然かね。


QMLとJavaScriptの連携ができたんで、次はクロスドメイン制約無しでXMLHttpRequestができるかどうかを試してみる。
それができればJavaScriptでパース処理書くだけで目的のFeedリーダーが作れそう。

だが、まだPlasmoidの設定ボタン押した時の処理の書き方がわからないな。
できれば、設定ボタン経由でFeedのアドレス設定ができるようにしたいし。