<週刊 自分のごちうサーチを作る> #6 ファイルがドロップされたときの処理
前回記事はこちら。
今回のお品書き。
- 初期化処理を書く
- ファイルが飛んできたときに対応
- URLが飛んできたときに対応
コア機能である,画像の検索までできるようにします。
リソースの追加
データベースファイルを元プロジェクトからコピーして追加します。Resources
フォルダをMyGochiusearch
プロジェクトに作成しましょう。ここに既存のファイルであるindex.txt
, index.db
を追加します。
ファイルがプロジェクトフォルダ配下にない場合はダイアログが出ます。ここではコピーしておきますが,リンクの追加でも実質問題ありません。
ビルド時に出力フォルダへコピーする設定をしておきます。
初期化処理
Gochiusearch
プロジェクトの MainForm.cs から初期化処理を引っ張ってきます。具体的にはMainForm
のコンストラクタから呼ばれている,LoadStoryInfo
とLoadImageInfo
です。
これをこのまま貼り付けて,よろしくない部分を修正していきましょう。MyGochiuseach
の MainWindowController
に貼り付けます。WindowDidLoad
から呼び出すようにしましょう。
LoadImageInfo
- imageSearch フィールドの作成
- リソースファイルのパスを解決
- メッセージボックスのコードを以前作成したユーティリティメソッドに変更
画像の特徴量は index.db
に格納されています。このファイルは先ほどリソースとして追加したので,このパスを与えて初期化します。元のWindows Formsアプリでは実行ファイルと同じ階層にある前提で作成されていますが,これはXamarin.Macでは使え,なくはないですが使いません。下記のように変更しましょう。
Resourcesフォルダ内のファイルはPathForResource
で解決できます。ファイル名と拡張子部分を与えます。パス文字列を生成しているだけなので,存在するかどうかはここでは判断されません。
LoadStoryInfo
話数の情報をテキストファイルに保持しています。LoadImageInfo と同様に,PathForResource
でパス文字列を構成するようにすればほとんど他にやることはありません。
フィールド名を合わせるぐらいでなにもしなくていいのですが,元ソースではテキストファイルの内容を一行ずつ処理しているので,LINQ でざくっと射影するようにしてみました。一行ずつ処理した方がエラー時スキップとか進捗報告とかできるので,あまりうまい方法ではないと思いますがネタとして。
ここまでできたら一度実行して,例外が発生しないことを確認しましょう。
ファイルのドロップに対応する
MainForm.cs
の FindImage
メソッドを移植していきます。元ソースでは画像の表示処理もここで行っているのですが,NSImage
はドロップ時に解釈できる場合は画像を表示してくれます(もちろん抑止できます)。実質必要なのは下記のような処理です。
- 最後に開いたファイルのパスを更新
- 結果出力のクリア
- 画像の特徴量を算出
- 特徴量に基づいて関連する画像情報を検索
- 抽出された情報を基に話数や位置の情報を文字列化
- 結果出力を行う
- 必要な場合はニコニコ動画を開く
下記のように実装します。
元ソースと比較して読んでいただければ概ね把握できると思います。ポイントとしてはURLをNSUrlにして,Process.Start
の代わりに SharedWorkspace.OpenUrl
にしています。
また,元ソースではリッチテキストボックスに直接書式設定していましたが,NSStringAttributes
を使ってリンクURLの規定の書式で結果ビューに出力させています。ここには複数の書式を設定できますし,リンクURLにしておけばクリック時の処理も自動でやってくれます。他にもいろんな属性があるのでIntellisenseから探してみてください。
また,下記のようにイベントを購読しておきます。検索レベルを変更したとき,すでにファイルが読み込まれている場合は再検索するようにします。
では実行してみましょう。
うまくいきましたか?
URLのドロップに対応する
MainForm.cs
ではドラッグ操作進入時にURLかどうかのフィールドを更新し,ドロップ時にURLだったときは同階層にBrowser
ファイルを作ってダウンロード処理を行っています。こうすることで画像検索側はファイル名だけ渡せばよくなるわけです。
Mac版でも同様の方法を踏襲します。URL判定は終わっているので,URL で指定されたファイルをダウンロードし,このパスをFindImage
メソッドに渡します。ただし,同階層にファイルを置くのは将来的なサンドボックス化を考えるとあまりうまい方法とは言えないので…
次回予告
- URLのドロップに対応する
Stay tuned.