読者です 読者をやめる 読者になる 読者になる

うさぎ駆動開発

UWP, Xamarin.Macを中心によしなしごとを書いていきます。

<週刊 自分のごちうサーチを作る> #6 ファイルがドロップされたときの処理

前回記事はこちら。

aile.hatenablog.com

今回のお品書き。

  • 初期化処理を書く
  • ファイルが飛んできたときに対応
  • URLが飛んできたときに対応

コア機能である,画像の検索までできるようにします。

リソースの追加

データベースファイルを元プロジェクトからコピーして追加します。Resources フォルダをMyGochiusearchプロジェクトに作成しましょう。ここに既存のファイルであるindex.txt, index.dbを追加します。

f:id:ailen0ada:20160605132252p:plain

f:id:ailen0ada:20160605132430p:plain

ファイルがプロジェクトフォルダ配下にない場合はダイアログが出ます。ここではコピーしておきますが,リンクの追加でも実質問題ありません。

f:id:ailen0ada:20160605132458p:plain

ビルド時に出力フォルダへコピーする設定をしておきます。

f:id:ailen0ada:20160605132747p:plain

初期化処理

Gochiusearch プロジェクトの MainForm.cs から初期化処理を引っ張ってきます。具体的にはMainFormのコンストラクタから呼ばれている,LoadStoryInfoLoadImageInfoです。

これをこのまま貼り付けて,よろしくない部分を修正していきましょう。MyGochiuseachMainWindowController に貼り付けます。WindowDidLoadから呼び出すようにしましょう。

LoadImageInfo

  1. imageSearch フィールドの作成
  2. リソースファイルのパスを解決
  3. メッセージボックスのコードを以前作成したユーティリティメソッドに変更

画像の特徴量は index.db に格納されています。このファイルは先ほどリソースとして追加したので,このパスを与えて初期化します。元のWindows Formsアプリでは実行ファイルと同じ階層にある前提で作成されていますが,これはXamarin.Macでは使え,なくはないですが使いません。下記のように変更しましょう。

Resourcesフォルダ内のファイルはPathForResourceで解決できます。ファイル名と拡張子部分を与えます。パス文字列を生成しているだけなので,存在するかどうかはここでは判断されません。

LoadStoryInfo

話数の情報をテキストファイルに保持しています。LoadImageInfo と同様に,PathForResourceでパス文字列を構成するようにすればほとんど他にやることはありません。

フィールド名を合わせるぐらいでなにもしなくていいのですが,元ソースではテキストファイルの内容を一行ずつ処理しているので,LINQ でざくっと射影するようにしてみました。一行ずつ処理した方がエラー時スキップとか進捗報告とかできるので,あまりうまい方法ではないと思いますがネタとして。

ここまでできたら一度実行して,例外が発生しないことを確認しましょう。

ファイルのドロップに対応する

MainForm.csFindImage メソッドを移植していきます。元ソースでは画像の表示処理もここで行っているのですが,NSImage はドロップ時に解釈できる場合は画像を表示してくれます(もちろん抑止できます)。実質必要なのは下記のような処理です。

  1. 最後に開いたファイルのパスを更新
  2. 結果出力のクリア
  3. 画像の特徴量を算出
  4. 特徴量に基づいて関連する画像情報を検索
  5. 抽出された情報を基に話数や位置の情報を文字列化
  6. 結果出力を行う
  7. 必要な場合はニコニコ動画を開く

下記のように実装します。

元ソースと比較して読んでいただければ概ね把握できると思います。ポイントとしてはURLをNSUrlにして,Process.Startの代わりに SharedWorkspace.OpenUrl にしています。

また,元ソースではリッチテキストボックスに直接書式設定していましたが,NSStringAttributesを使ってリンクURLの規定の書式で結果ビューに出力させています。ここには複数の書式を設定できますし,リンクURLにしておけばクリック時の処理も自動でやってくれます。他にもいろんな属性があるのでIntellisenseから探してみてください。

また,下記のようにイベントを購読しておきます。検索レベルを変更したとき,すでにファイルが読み込まれている場合は再検索するようにします。

では実行してみましょう。

f:id:ailen0ada:20160605142200p:plain

うまくいきましたか?

URLのドロップに対応する

MainForm.cs ではドラッグ操作進入時にURLかどうかのフィールドを更新し,ドロップ時にURLだったときは同階層にBrowserファイルを作ってダウンロード処理を行っています。こうすることで画像検索側はファイル名だけ渡せばよくなるわけです。

Mac版でも同様の方法を踏襲します。URL判定は終わっているので,URL で指定されたファイルをダウンロードし,このパスをFindImageメソッドに渡します。ただし,同階層にファイルを置くのは将来的なサンドボックス化を考えるとあまりうまい方法とは言えないので…

次回予告

  • URLのドロップに対応する

Stay tuned.