QUrl をローカルファイルに変換する
Qt Quick では、(主に画像ですがその他形式のファイルなどの)外部のリソースを扱う際に QUrl 形式を利用します。
- Image エレメントの source プロパティ
- Loader エレメントの source プロパティ
- FontLoader エレメントの source プロパティ
- ShaderEffect エレメントの fragmentShader と vertexShader プロパティ
Starting from Qt 5.8 ShaderEffect also supports reading the GLSL source code from files. Whenever the fragmentShader or vertexShader property value is a URL with the file or qrc schema, it is treated as a file reference and the source code is read from the specified file.
OpenGL and GLSL – ShaderEffect QML Type
こういった既存のものや、カスタムエレメントなどの url 型のプロパティを C++ から扱う際には、その URL が
- ローカルのファイルなのか(file://〜)
- Qt のリソース に含まれるファイルのか(qrc:/〜)
- ネットワーク経由のファイルなのか(https://〜)
- (Android の場合は、assets:/ および content:/ なのか)
などに応じて処理を変える必要があります。
具体的には、QUrl の scheme() メソッドの返り値を取得し、それが file なのか qrc なのか https? なのかに応じて分岐するようなコードが必要になります。
しかし、Qt のファイルやパスを扱うクラスではローカルファイル(/〜)とリソース内のファイル(:/〜)は同じように扱える上に、ネットワーク経由のものを扱うケースはほぼないため、ローカルファイルとリソースのファイルを共通に扱えるようにしたい!という願望があります。
QUrl::toLocalFile() はこのためにあるようなメソッドですが、ローカルファイルのみの対応で、リソースファイルには残念ながら対応していません。
でも大丈夫。特に QML の下回りでこういったケースが多発するためか、QtQml モジュールにはそれを実現してくれる機能が用意してあります。
class Q_QML_EXPORT QQmlFile
{
....
static bool isLocalFile(const QUrl &url);
QString urlToLocalFileOrQrc(const QUrl &);
....
qtdeclarative/src/qml/qml/qqmlfile.h};
アプリケーション開発者がよく使うものではないため、ドキュメント等はありませんが、外部からも利用できるよう、Q_QML_EXPORT が記載されていますので、QT += qml と #include <QtQml/QQmlFile> でこの機能が使えるようになります。
本来は QUrl で対応してもいいと思いますが、こういうことで困るのは大体 QtQml のモジュールを利用している時なので、まぁいいか、ありがとうという気持ちで積極的に利用していきましょう!
余談ですが、この機能を利用して、以前 こんな Qt のバグ を こうやって修正 しました。