凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

QtQuick で簡単なファイルブラウザを作る

はじめに

ファイルブラウザ欲しいな、と思ったところ FolderListModel という要素を見つけました。

これをリストビューで表示してちょっといじって移動できる簡単なファイルブラウザを作成したというお話です。

環境

基礎

QML ではディレクトリをインポートすることで、そのディレクトリに含まれる QML のファイル名を要素として使えるようになります。例えば以下の様な Hoge.qml を作成します。

import QtQuick 2.0

Rectangle {
	property alias textColor: text.color
	Text {
		id: text
		anchors.centerIn: parent
		text: 'HOGE'
	}
}

これを同一ディレクトリ内の Fuga.qml から以下のように使います。

import QtQuick 2.0
import './'

Hoge {
	width: 360
	height: 360
	color: '#000'
	textColor: '#fff'
}

Fuga.qml を実行すると以下のようになります。

ルート要素のプロパティはそのまま書き換えることができ、子要素に関しても alias を設定してあげれば書き換えられるようになります。初期値を与えたい時は以下のようにすると良いと思います。

import QtQuick 2.0

Rectangle {
	property color textColor: '#fff'
	Text {
		id: text
		anchors.centerIn: parent
		color: textColor
		text: 'HOGE'
	}
}

これを利用して import できる FileListView.qml を作ってみました。

ソース

import QtQuick 2.0
import Qt.labs.folderlistmodel 1.0

ListView {
    id: list
    model: folderModel
    delegate: fileDelegate
    highlight: highlight
    clip: true

    property color color: "#333333"
    property color highlightColor: "#44ffaa"
    property variant filters: []
    property string folder: "/Users"
    property int itemHeight: 24
    property string selectedItem: ""

    FolderListModel {
        id: folderModel
        nameFilters: list.filters
        folder: list.folder
        showDirsFirst: true
        showDotAndDotDot: true
    }

    Component {
        id: fileDelegate
        Item {
            width: parent.width
            height: list.itemHeight
            Text {
                id: item
                anchors.verticalCenter: parent.verticalCenter
                text: fileName
                color: list.color
            }
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    list.currentIndex = index;
                }
                onDoubleClicked: {
                    list.currentIndex = index;
                    var selectedFolder = currentItem.children[0].text;
                    if (list.folder === '/') {
                        list.folder += selectedFolder;
                    }
                    else if (selectedFolder === '..') {
                        list.folder = list.folder.replace(/\/[^\/]*$/, '');
                    }
                    else {
                        list.folder += '/' + selectedFolder;
                    }
                }
            }
        }
    }

    Component {
        id: highlight
        Rectangle {
            id: highlightBar
            width: list.width
            height: list.itemHeight
            color: highlightColor
            y: list.currentItem.y
            Behavior on y {
                PropertyAnimation {
                    duration: 100
                }
            }
        }
    }
}

FolderListModel を ListView のモデルにして、後は選択した要素をハイライトするデリゲータを書いています。これを利用するコードは以下のようになります。

import QtQuick 2.0
import "./"

Rectangle {
    width: 360
    height: 360
    color: '#000'
    Text {
        id: currentFolder
        width: parent.width
        height: 30
        verticalAlignment: Text.AlignVCenter
        text: fileList.folder
        color: '#fff'
        anchors.left: parent.left
        anchors.top: parent.top
    }
    FileListView {
        id: fileList
        width: parent.width
        color: '#aaa'
        highlightColor: '#555'
        filters: ['*.jpg', '*.JPG']
        anchors.top: currentFolder.bottom;
        anchors.bottom: parent.bottom
    }
}

実行すると以下のようになります。


おわりに

もっと混みいったことをしようとすると FileListModel の機能は物足りないので、C++ 側と連携する必要がありそうです。