Qt Macでアプリケーションアイコンへのドラッグ&ドロップに対応する

この前Qtを使ってMacでアプリケーションを作成したとき、アプリケーションのアイコンへファイルのドラッグ&ドロップしても何も反応しないことに気が付きました。
Windowsだとコマンドライン引数としてドロップしたファイルのパスが渡された状態でアプリケーションが起動しますよね。
とりあえずいろいろ調べてみてMacでもファイルのドラッグ&ドロップに対応することができたので、自分のやった方法をまとめようと思います。

一番参考になったのは下のブログの記事のコメント欄でした。
Macだと arguments が渡ってこない - Qtプログラミング日記

ドラッグ&ドロップ対応に必要なこと

ドラッグ&ドロップ対応に必要なことですが以下の2つのことをする必要がありました。

1. info.plistを編集してドラッグ&ドロップを有効化する
2. QApplicationのevent関数をオーバーライドしてドロップしたときの処理を書く

info.plistの編集

まずinfo.plistを編集してアプリケーションが対応するファイル形式を設定する必要があります。
info.plist*.app/Contentsの中にあり、アプリケーションの設定などが記述されたxml形式のファイルです。
この中にCFBundleDocumentTypesという項目を追加して対応させたいファイル形式を設定します。

CFBundleDocumentTypesについてはiOS向けの記事ですが以下の記事が参考になりました。
Safx: iOSアプリケーションを特定のファイル形式に対応させる方法について

例えば以下のような項目を追加するとファイルの種類を問わず(ディレクトリでも)ドラッグ&ドロップが有効になります。

<key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string></string>
            <key>LSHandlerRank</key>
            <string>Alternate</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.item</string>
            </array>
        </dict>
    </array>

Xcodeがインストールされていれば下の画像のような専用のエディタで開くことができます。

※赤枠部分が追加部分
f:id:nukesaq88:20130501223233p:plain

また.proファイルに以下のように記述することで予め用意したInfo.plistを指定することができます。

QMAKE_INFO_PLIST = Info.plist

ドロップされた場合の処理

次にQApplicationのevent関数をオーバーライドしてドロップしたときの処理を書きます。
例として以下ではMyApplicationというQApplicationを継承したクラスを作成し、その中でevent関数をオーバーライドしています。

class MyApplication : public QApplication
{
public:
  MyApplication( int &argc, char **argv ) :
    QApplication( argc, argv )
  { }

protected:

  virtual bool event( QEvent * e )
  {
    if( e->type() == QEvent::FileOpen )
    {
      const QFileOpenEvent * const file_event = static_cast<QFileOpenEvent *>(e);
      const QString file = file_event->file();
      /*
      fileをごにょごにょ
      */
      return true;
    }
    return QApplication::event(e);
  }

};

このクラスのインスタンスがQApplicationの代わりにmain関数で生成されるようにすればOKです。

まとめ

このような方法でMacでもドラッグ&ドロップに対応したQtアプリを作成することができました。
少々めんどくさいですが、対応させるファイル形式を指定できたり、起動中もドロップイベントを処理できたりと便利な面も多いですね。

参考
Macだと arguments が渡ってこない - Qtプログラミング日記
Mac OS X: Handling Apple Events
Safx: iOSアプリケーションを特定のファイル形式に対応させる方法について
System-Declared Uniform Type Identifiers