QUrl をローカルファイルに変換する

Qt Quick では、(主に画像ですがその他形式のファイルなどの)外部のリソースを扱う際に QUrl 形式を利用します。

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 のバグこうやって修正 しました。