Qt環境のアプリから別のMac OS X .app形式のアプリでファイルを開く メモ

Qt環境のアプリから別のMac OS X .app形式のアプリでファイルを開きたかったので、QProcessから.app形式のアプリに引数でファイルパスを渡してやれば大丈夫だろうと思っていたのですが、あまり上手くいきませんでした。

例えばPreview.apphoge.pngを開きたい場合

QProcess::execute( "/Applications/Preview.app hoge.png" );

を実行してみたところPreview.appでhoge.pngは開いたのですが、Preview.appを終了しても処理が戻って来ず、アプリがハングアップした状態になりました。
なのでexecute関数をプロセスをアプリとは切り離して実行するstartDetachedに変えてみると、こちらはPreview.appすら起動せずboolの戻り値もfalseになっていました。

そこでいろいろ調べたり考えたりしたところ、Mac標準のPythonPyObjCというモジュールが統合されており、これを用いれば簡単にcocoaAPIを呼べそうということが分かりました。

ということで早速試してみたのですが、結論を言えば無事成功しました。

以下がそのコードです。

const QString script =
          "# -*- coding: utf-8-mac -*-\n"
          "import AppKit\n"
          "w = AppKit.NSWorkspace.sharedWorkspace()\n"
          "w.openFile_withApplication_( '/Users/user/Desktop/hoge.png', 'Preview')\n";

QStringList args;
args.push_back( "-c" );
args.push_back( script );
QProcess::execute( "/usr/bin/python", args );

-cというオプションをつければPythonは直接コマンドライン引数で実行するスクリプトを渡せます。
また文字コードutf-8-macを指定しないと日本語が入ったファイルパスでは失敗します。

上記を関数にしておけば簡単に呼び出せるようになりますね。

まとめ

PyObjCは今回はじめて利用しましたが、Objectiv-C以外の環境でちょこっとcocoaのAPIを利用したい場合には結構使い所がありそういうことが分かりました。さらにRubyにもRubyCocoaというモジュールがMacでは搭載されているためこちらを使っても問題なさそうです。

また、PyObjCとか使わなくてももっと簡単な方法があるよー って場合は教えていただけるとうれしいです。

MacDevCenter.com
Introduction — PyObjC — the Python ⟷ Objective-C bridge
PyObjC - Wikipedia