1 // ================================================================================================
3 // Wikipedia翻訳支援ツール主画面クラスソース</summary>
5 // <copyright file="MainForm.cs" company="honeplusのメモ帳">
6 // Copyright (C) 2011 Honeplus. All rights reserved.</copyright>
9 // ================================================================================================
11 namespace Honememo.Wptscs
14 using System.Collections.Generic;
15 using System.ComponentModel;
20 using System.Windows.Forms;
21 using Honememo.Utilities;
22 using Honememo.Wptscs.Logics;
23 using Honememo.Wptscs.Models;
24 using Honememo.Wptscs.Properties;
27 /// Wikipedia翻訳支援ツール主画面のクラスです。
29 public partial class MainForm : Form
34 /// 現在読み込んでいるアプリケーションの設定。
36 private Config config;
41 private Translator translate;
46 private int logLastLength;
53 /// コンストラクタ。初期化メソッド呼び出しのみ。
57 // Windows フォーム デザイナで生成されたコード
58 this.InitializeComponent();
68 /// <param name="sender">イベント発生オブジェクト。</param>
69 /// <param name="e">発生したイベント。</param>
70 private void MainForm_Load(object sender, EventArgs e)
73 if (!this.LoadConfig())
75 // 読み込み失敗時はどうしようもないのでそのまま終了
79 this.translate = null;
80 Control.CheckForIllegalCrossThreadCalls = false;
86 this.textBoxSaveDirectory.Text = Settings.Default.SaveDirectory;
87 this.comboBoxSource.SelectedText = Settings.Default.LastSelectedSource;
88 this.comboBoxTarget.SelectedText = Settings.Default.LastSelectedTarget;
91 this.ComboBoxSource_SelectedIndexChanged(sender, e);
92 this.ComboBoxTarget_SelectedIndexChanged(sender, e);
96 /// フォームクローズ時の処理。処理状態を保存。
98 /// <param name="sender">イベント発生オブジェクト。</param>
99 /// <param name="e">発生したイベント。</param>
100 private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
102 // 現在の作業フォルダ、絞込み文字列を保存
103 Settings.Default.SaveDirectory = this.textBoxSaveDirectory.Text;
104 Settings.Default.LastSelectedSource = this.comboBoxSource.Text;
105 Settings.Default.LastSelectedTarget = this.comboBoxTarget.Text;
106 Settings.Default.Save();
110 /// 翻訳元コンボボックス変更時の処理。
112 /// <param name="sender">イベント発生オブジェクト。</param>
113 /// <param name="e">発生したイベント。</param>
114 private void ComboBoxSource_SelectedIndexChanged(object sender, EventArgs e)
117 this.labelSource.Text = String.Empty;
118 this.linkLabelSourceURL.Text = "http://";
119 if (!String.IsNullOrWhiteSpace(this.comboBoxSource.Text))
121 this.comboBoxSource.Text = this.comboBoxSource.Text.Trim().ToLower();
123 // その言語の、ユーザーが使用している言語での表示名を表示
124 // (日本語環境だったら日本語を、英語だったら英語を)
125 Language.LanguageName name;
126 this.labelSource.Text = String.Empty;
127 if (this.config.GetWebsite(this.comboBoxSource.Text) != null &&
128 this.config.GetWebsite(this.comboBoxSource.Text).Language.Names.TryGetValue(
129 System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName,
132 this.labelSource.Text = name.Name;
136 this.linkLabelSourceURL.Text = this.config.GetWebsite(
137 this.comboBoxSource.Text).Location;
142 /// 翻訳元コンボボックスフォーカス喪失時の処理。
144 /// <param name="sender">イベント発生オブジェクト。</param>
145 /// <param name="e">発生したイベント。</param>
146 private void ComboBoxSource_Leave(object sender, EventArgs e)
148 // 直接入力された場合の対策、変更時の処理をコール
149 this.ComboBoxSource_SelectedIndexChanged(sender, e);
153 /// リンクラベルのリンククリック時の処理。
155 /// <param name="sender">イベント発生オブジェクト。</param>
156 /// <param name="e">発生したイベント。</param>
157 private void LinkLabelSourceURL_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
160 System.Diagnostics.Process.Start(((LinkLabel)sender).Text);
164 /// 翻訳先コンボボックス変更時の処理。
166 /// <param name="sender">イベント発生オブジェクト。</param>
167 /// <param name="e">発生したイベント。</param>
168 private void ComboBoxTarget_SelectedIndexChanged(object sender, EventArgs e)
171 this.labelTarget.Text = String.Empty;
172 if (!String.IsNullOrWhiteSpace(this.comboBoxTarget.Text))
174 this.comboBoxTarget.Text = this.comboBoxTarget.Text.Trim().ToLower();
176 // その言語の、ユーザーが使用している言語での表示名を表示
177 // (日本語環境だったら日本語を、英語だったら英語を)
178 if (this.config.GetWebsite(
179 this.comboBoxTarget.Text) != null)
181 this.labelTarget.Text = this.config.GetWebsite(
182 this.comboBoxTarget.Text).Language.Names[System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName].Name;
188 /// 翻訳先コンボボックスフォーカス喪失時の処理。
190 /// <param name="sender">イベント発生オブジェクト。</param>
191 /// <param name="e">発生したイベント。</param>
192 private void ComboBoxTarget_Leave(object sender, EventArgs e)
194 // 直接入力された場合の対策、変更時の処理をコール
195 this.ComboBoxTarget_SelectedIndexChanged(sender, e);
201 /// <param name="sender">イベント発生オブジェクト。</param>
202 /// <param name="e">発生したイベント。</param>
203 private void ButtonConfig_Click(object sender, EventArgs e)
206 ConfigForm form = new ConfigForm(this.config);
209 // 戻ってきたら設定ファイルを再読み込み
214 string backupSourceSelected = this.comboBoxSource.SelectedText;
215 string backupSourceTarget = this.comboBoxTarget.SelectedText;
217 this.comboBoxSource.SelectedText = backupSourceSelected;
218 this.comboBoxTarget.SelectedText = backupSourceTarget;
221 this.ComboBoxSource_SelectedIndexChanged(sender, e);
222 this.ComboBoxTarget_SelectedIndexChanged(sender, e);
228 /// <param name="sender">イベント発生オブジェクト。</param>
229 /// <param name="e">発生したイベント。</param>
230 private void ButtonSaveDirectory_Click(object sender, EventArgs e)
232 // フォルダ名が入力されている場合、それを初期位置に設定
233 if (!String.IsNullOrEmpty(this.textBoxSaveDirectory.Text))
235 this.folderBrowserDialogSaveDirectory.SelectedPath = this.textBoxSaveDirectory.Text;
239 if (this.folderBrowserDialogSaveDirectory.ShowDialog() == System.Windows.Forms.DialogResult.OK)
241 // フォルダが選択された場合、フォルダ名に選択されたフォルダを設定
242 this.textBoxSaveDirectory.Text = this.folderBrowserDialogSaveDirectory.SelectedPath;
247 /// 出力先テキストボックスフォーカス喪失時の処理。
249 /// <param name="sender">イベント発生オブジェクト。</param>
250 /// <param name="e">発生したイベント。</param>
251 private void TextBoxSaveDirectory_Leave(object sender, EventArgs e)
254 this.textBoxSaveDirectory.Text = this.textBoxSaveDirectory.Text.Trim();
260 /// <param name="sender">イベント発生オブジェクト。</param>
261 /// <param name="e">発生したイベント。</param>
262 private void ButtonRun_Click(object sender, EventArgs e)
265 if (String.IsNullOrWhiteSpace(this.comboBoxSource.Text))
267 FormUtils.WarningDialog(Resources.WarningMessageNotSelectedSource);
268 this.comboBoxSource.Focus();
271 else if (String.IsNullOrWhiteSpace(this.comboBoxTarget.Text))
273 FormUtils.WarningDialog(Resources.WarningMessageNotSelectedTarget);
274 this.comboBoxTarget.Focus();
277 else if (!String.IsNullOrWhiteSpace(this.comboBoxSource.Text)
278 && this.comboBoxSource.Text == this.comboBoxTarget.Text)
280 FormUtils.WarningDialog(Resources.WarningMessageEqualsSourceAndTarget);
281 this.comboBoxTarget.Focus();
284 else if (String.IsNullOrWhiteSpace(this.textBoxSaveDirectory.Text))
286 FormUtils.WarningDialog(Resources.WarningMessageEmptySaveDirectory);
287 this.textBoxSaveDirectory.Focus();
290 else if (!Directory.Exists(this.textBoxSaveDirectory.Text))
292 FormUtils.WarningDialog(Resources.WarningMessageIgnoreSaveDirectory);
293 this.textBoxSaveDirectory.Focus();
296 else if (String.IsNullOrWhiteSpace(this.textBoxArticle.Text))
298 FormUtils.WarningDialog(Resources.WarningMessageEmptyArticle);
299 this.textBoxArticle.Focus();
304 this.LockOperation();
307 this.backgroundWorkerRun.RunWorkerAsync();
313 /// <param name="sender">イベント発生オブジェクト。</param>
314 /// <param name="e">発生したイベント。</param>
315 private void ButtonStop_Click(object sender, EventArgs e)
318 this.buttonStop.Enabled = false;
319 if (this.backgroundWorkerRun.IsBusy == true)
321 System.Diagnostics.Debug.WriteLine("MainForm.-Stop_Click > 処理中断");
322 this.backgroundWorkerRun.CancelAsync();
323 if (this.translate != null)
325 this.translate.CancellationPending = true;
331 /// 実行ボタン バックグラウンド処理(スレッド)。
333 /// <param name="sender">イベント発生オブジェクト。</param>
334 /// <param name="e">発生したイベント。</param>
335 private void BackgroundWorkerRun_DoWork(object sender, DoWorkEventArgs e)
340 this.textBoxLog.Clear();
341 this.logLastLength = 0;
342 this.textBoxLog.AppendText(
344 Resources.LogMessage_Start,
345 FormUtils.ApplicationName(),
346 DateTime.Now.ToString("F")));
348 // 処理結果とログのための出力ファイル名を作成
351 this.MakeFileName(out fileName, out logName, this.textBoxArticle.Text.Trim(), this.textBoxSaveDirectory.Text);
353 // 翻訳支援処理を実行し、結果とログをファイルに出力
356 this.translate = Translator.Create(this.config, this.comboBoxSource.Text, this.comboBoxTarget.Text);
358 catch (NotImplementedException)
361 this.textBoxLog.AppendText(String.Format(Resources.InformationMessage_DevelopingMethod, "Wikipedia以外の処理"));
362 FormUtils.InformationDialog(Resources.InformationMessage_DevelopingMethod, "Wikipedia以外の処理");
366 this.translate.LogUpdate += new EventHandler(this.GetLogUpdate);
368 // 実行前に、ユーザーから中止要求がされているかをチェック
369 if (this.backgroundWorkerRun.CancellationPending)
371 this.textBoxLog.AppendText(String.Format(Resources.LogMessage_Stop, logName));
376 bool successFlag = this.translate.Run(this.textBoxArticle.Text.Trim());
378 // 処理に時間がかかるため、出力ファイル名を再確認
379 this.MakeFileName(out fileName, out logName, this.textBoxArticle.Text.Trim(), this.textBoxSaveDirectory.Text);
385 StreamWriter sw = new StreamWriter(Path.Combine(this.textBoxSaveDirectory.Text, fileName));
388 sw.Write(this.translate.Text);
389 this.textBoxLog.AppendText(String.Format(Resources.LogMessage_End, fileName, logName));
398 this.textBoxLog.AppendText(String.Format(Resources.LogMessage_ErrorFileSave, Path.Combine(this.textBoxSaveDirectory.Text, fileName), ex.Message));
399 this.textBoxLog.AppendText(String.Format(Resources.LogMessage_Stop, logName));
404 this.textBoxLog.AppendText(String.Format(Resources.LogMessage_Stop, logName));
411 StreamWriter sw = new StreamWriter(Path.Combine(this.textBoxSaveDirectory.Text, logName));
414 sw.Write(this.textBoxLog.Text);
423 this.textBoxLog.AppendText(String.Format(Resources.LogMessage_ErrorFileSave, Path.Combine(this.textBoxSaveDirectory.Text, logName), ex.Message));
428 this.textBoxLog.AppendText("\r\n" + String.Format(Resources.ErrorMessageDevelopmentError, ex.Message, ex.StackTrace) + "\r\n");
429 System.Diagnostics.Debug.WriteLine("MainForm.backgroundWorkerRun_DoWork > 想定外のエラー : " + ex.Message);
430 System.Diagnostics.Debug.WriteLine(ex.StackTrace);
435 /// 実行ボタン バックグラウンド処理(終了時)。
437 /// <param name="sender">イベント発生オブジェクト。</param>
438 /// <param name="e">発生したイベント。</param>
439 private void BackgroundWorkerRun_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
444 this.config.Save(Settings.Default.ConfigurationFile);
448 FormUtils.WarningDialog(
449 Resources.WarningMessageCacheSaveFailed,
464 private void Initialize()
467 this.comboBoxSource.Items.Clear();
468 this.comboBoxTarget.Items.Clear();
470 // 設定ファイルに存在する全言語を選択肢として登録する
471 foreach (Website site in this.config.Websites)
473 this.comboBoxSource.Items.Add(site.Language.Code);
474 this.comboBoxTarget.Items.Add(site.Language.Code);
481 /// <returns>読み込み成功時は<c>true</c>。</returns>
482 private bool LoadConfig()
487 this.config = Config.GetInstance(Settings.Default.ConfigurationFile);
489 catch (FileNotFoundException ex)
492 System.Diagnostics.Debug.WriteLine(
493 "MainForm.LoadConfig > 設定ファイル読み込み失敗 : " + ex.Message);
494 FormUtils.ErrorDialog(
495 Resources.ErrorMessageConfigNotFound,
496 Settings.Default.ConfigurationFile);
502 System.Diagnostics.Debug.WriteLine(
503 "MainForm.LoadConfig > 設定ファイル読み込み時エラー : " + ex.StackTrace);
504 FormUtils.ErrorDialog(
505 Resources.ErrorMessageConfigLordFailed,
517 private void LockOperation()
520 this.groupBoxTransfer.Enabled = false;
521 this.groupBoxSaveDirectory.Enabled = false;
522 this.textBoxArticle.Enabled = false;
523 this.buttonRun.Enabled = false;
526 this.buttonStop.Enabled = true;
532 private void Release()
535 this.buttonStop.Enabled = false;
538 this.groupBoxTransfer.Enabled = true;
539 this.groupBoxSaveDirectory.Enabled = true;
540 this.textBoxArticle.Enabled = true;
541 this.buttonRun.Enabled = true;
545 /// 渡された文字列から.txtと.logの重複していないファイル名を作成。
547 /// <param name="fileName">出力結果ファイル名。</param>
548 /// <param name="logName">出力ログファイル名。</param>
549 /// <param name="text">出力する結果テキスト。</param>
550 /// <param name="dir">出力先ディレクトリ。</param>
551 /// <returns><c>true</c> 出力成功</returns>
552 private bool MakeFileName(out string fileName, out string logName, string text, string dir)
554 // 出力先フォルダに存在しないファイル名(の拡張子より前)を作成
555 // ※渡されたWikipedia等の記事名にファイル名に使えない文字が含まれている場合、_ に置き換える
556 // また、ファイル名が重複している場合、xx[0].txtのように連番を付ける
557 string fileNameBase = FormUtils.ReplaceInvalidFileNameChars(text);
558 fileName = fileNameBase + ".txt";
559 logName = fileNameBase + ".log";
560 bool success = false;
561 for (int i = 0; i < 100000; i++)
563 // ※100000まで試して空きが見つからないことは無いはず、もし見つからなかったら最後のを上書き
564 if (!File.Exists(Path.Combine(dir, fileName))
565 && !File.Exists(Path.Combine(dir, logName)))
571 fileName = fileNameBase + "[" + i + "]" + ".txt";
572 logName = fileNameBase + "[" + i + "]" + ".log";
582 /// <param name="sender">イベント発生オブジェクト。</param>
583 /// <param name="e">発生したイベント。</param>
584 private void GetLogUpdate(object sender, System.EventArgs e)
586 // 前回以降に追加されたログをテキストボックスに出力
587 int length = this.translate.Log.Length;
588 if (length > this.logLastLength)
590 this.textBoxLog.AppendText(this.translate.Log.Substring(this.logLastLength, length - this.logLastLength));
593 this.logLastLength = length;