PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/MP-TVSeries/Configuration/ImportPanelEpID.cs

http://mptvseries.googlecode.com/
C# | 306 lines | 254 code | 40 blank | 12 comment | 60 complexity | bbf4ba31d8c5a715d7688b0cd7213811 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Data;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.Globalization;
  10. namespace WindowPlugins.GUITVSeries.Configuration
  11. {
  12. public partial class ImportPanelEpID : UserControl, Feedback.IEpisodeMatchingFeedback
  13. {
  14. public event UserFinishedEditingDelegate UserFinishedEditing;
  15. bool isFinished = false;
  16. Dictionary<DBSeries, List<DBEpisode>> localeps = new Dictionary<DBSeries, List<DBEpisode>>();
  17. Dictionary<DBSeries, List<DBOnlineEpisode>> onlineeps = new Dictionary<DBSeries, List<DBOnlineEpisode>>();
  18. List<KeyValuePair<DBSeries, List<KeyValuePair<DBEpisode, DBOnlineEpisode>>>> matches = new List<KeyValuePair<DBSeries, List<KeyValuePair<DBEpisode, DBOnlineEpisode>>>>();
  19. List<DBEpisode> displayedEps = new List<DBEpisode>();
  20. List<DBOnlineEpisode> displayedOEps = new List<DBOnlineEpisode>();
  21. delegate void MatchEpisodesForSeriesDelegate(DBSeries series, List<DBEpisode> localEpisodes, List<DBOnlineEpisode> onlineCandidates);
  22. delegate List<KeyValuePair<DBSeries, List<KeyValuePair<DBEpisode, DBOnlineEpisode>>>> GetResultDelegate(bool showonly);
  23. public ImportPanelEpID()
  24. {
  25. InitializeComponent();
  26. }
  27. public void MatchEpisodesForSeries(DBSeries series, List<DBEpisode> localEpisodes, List<DBOnlineEpisode> onlineCandidates)
  28. {
  29. if (this.InvokeRequired)
  30. this.Invoke(new MatchEpisodesForSeriesDelegate(MatchEpisodesForSeries), series, localEpisodes, onlineCandidates);
  31. // only those not id'ed before
  32. tryAddToList(series, localEpisodes, localeps);
  33. tryAddToList(series, onlineCandidates, onlineeps);
  34. }
  35. private void FillSeriesList()
  36. {
  37. this.listBoxSeries.Items.Clear();
  38. this.listBoxOnline.Items.Clear();
  39. this.listBoxLocal.Items.Clear();
  40. foreach (var s in matches.Where(leps => leps.Value.Count > 0).Select(m => m.Key))
  41. {
  42. if (!listBoxSeries.Items.Contains(s))
  43. {
  44. if(!checkBoxFilter.Checked || !seriesHasAllEpsMatched(s))
  45. this.listBoxSeries.Items.Add(s);
  46. }
  47. }
  48. if (listBoxSeries.SelectedIndex < 0 && listBoxSeries.Items.Count > 0)
  49. listBoxSeries.SelectedIndex = 0;
  50. if (listBoxSeries.Items.Count == 0)
  51. {
  52. comboMatchOptions.Enabled = false;
  53. comboMatchOptions.Items.Clear();
  54. buttonMatchAgain.Enabled = false;
  55. txtBoxStatusBar.Text = "There are no episodes requiring manual selection...";
  56. }
  57. else
  58. {
  59. comboMatchOptions.Enabled = true;
  60. buttonMatchAgain.Enabled = true;
  61. }
  62. }
  63. private bool seriesHasAllEpsMatched(DBSeries series)
  64. {
  65. int unMatchedCount = matches.Single(s => s.Key == series).Value.Count(p => p.Value == null);
  66. return unMatchedCount == 0;
  67. }
  68. private void tryAddToList<T>(DBSeries series, List<T> episodes, Dictionary<DBSeries, List<T>> dic)
  69. {
  70. if (dic.ContainsKey(series))
  71. dic[series] = episodes;
  72. else dic.Add(series, episodes);
  73. }
  74. public WindowPlugins.GUITVSeries.Feedback.ReturnCode GetResult(out List<KeyValuePair<DBSeries, List<KeyValuePair<DBEpisode, DBOnlineEpisode>>>> result)
  75. {
  76. if (this.InvokeRequired)
  77. this.Invoke(new GetResultDelegate(getResultImpl), true);
  78. else getResultImpl(true);
  79. while (!isFinished) System.Threading.Thread.Sleep(1000); // block thread till we are done
  80. if (this.InvokeRequired)
  81. result = this.Invoke(new GetResultDelegate(getResultImpl), false) as List<KeyValuePair<DBSeries, List<KeyValuePair<DBEpisode, DBOnlineEpisode>>>>;
  82. else result = getResultImpl(false);
  83. return WindowPlugins.GUITVSeries.Feedback.ReturnCode.OK;
  84. }
  85. private List<KeyValuePair<DBSeries, List<KeyValuePair<DBEpisode, DBOnlineEpisode>>>> getResultImpl(bool requestShowOnly)
  86. {
  87. if (requestShowOnly)
  88. {
  89. if (UserFinishedEditing != null)
  90. {
  91. UserFinishedEditing(null, UserFinishedRequestedAction.ShowMe);
  92. ImportWizard.OnWizardNavigate += new ImportWizard.WizardNavigateDelegate(ImportWizard_OnWizardNavigate);
  93. }
  94. DoAutoMatchingForAll();
  95. FillSeriesList();
  96. return null;
  97. }
  98. else
  99. {
  100. bool isSecondPart = false;
  101. // update local episode ids with chosen episode ids
  102. foreach (var series in matches)
  103. {
  104. foreach (var pair in series.Value)
  105. {
  106. if (pair.Value != null)
  107. {
  108. // check if its a double episode
  109. isSecondPart = false;
  110. if (!string.IsNullOrEmpty(pair.Key[DBEpisode.cCompositeID2]))
  111. {
  112. // check if its the second part of a double episode
  113. if (pair.Key[DBEpisode.cEpisodeIndex] == pair.Key[DBEpisode.cEpisodeIndex2])
  114. isSecondPart = true;
  115. }
  116. pair.Key.ChangeIndexes(pair.Value[DBOnlineEpisode.cSeasonIndex], pair.Value[DBOnlineEpisode.cEpisodeIndex], isSecondPart);
  117. }
  118. }
  119. }
  120. return matches;
  121. }
  122. }
  123. private void DoAutoMatchingForAll()
  124. {
  125. foreach (var series in localeps)
  126. {
  127. DoAutoMatching(series.Key, null);
  128. }
  129. }
  130. private void DoAutoMatching(DBSeries series, string orderingOption)
  131. {
  132. var seriesMatches = matches.SingleOrDefault(kv => kv.Key == series);
  133. List<DBEpisode> localEps = localeps[series];
  134. var newseriesMatches = new List<KeyValuePair<DBEpisode, DBOnlineEpisode>>();
  135. foreach (var localEp in localEps)
  136. {
  137. var bestMatchVal = from oe in onlineeps.Single(s => s.Key == series).Value
  138. select new { Episode = oe, MatchValue = OnlineParsing.matchOnlineToLocalEpisode(series, localEp, oe, orderingOption) };
  139. var matchedEp = bestMatchVal.OrderBy(me => me.MatchValue).FirstOrDefault(me => me.MatchValue < int.MaxValue);
  140. if (matchedEp != null)
  141. newseriesMatches.Add(new KeyValuePair<DBEpisode, DBOnlineEpisode>(localEp, matchedEp.Episode));
  142. else newseriesMatches.Add(new KeyValuePair<DBEpisode, DBOnlineEpisode>(localEp, null));
  143. }
  144. if (seriesMatches.Key != null)
  145. matches.Remove(seriesMatches);
  146. matches.Add(new KeyValuePair<DBSeries, List<KeyValuePair<DBEpisode, DBOnlineEpisode>>>(series, newseriesMatches));
  147. }
  148. private void ImportWizard_OnWizardNavigate(UserFinishedRequestedAction reqAction)
  149. {
  150. if (reqAction == UserFinishedRequestedAction.Next) isFinished = true;
  151. if (UserFinishedEditing != null)
  152. UserFinishedEditing(null, reqAction);
  153. // we no longer need to listen to navigate event
  154. ImportWizard.OnWizardNavigate -= new ImportWizard.WizardNavigateDelegate(ImportWizard_OnWizardNavigate);
  155. }
  156. private void listBoxSeries_SelectedIndexChanged(object sender, EventArgs e)
  157. {
  158. var selectedSeries = listBoxSeries.SelectedItem as DBSeries;
  159. var selectedSeriesListLocal = localeps[selectedSeries];
  160. var selectedSeriesListOnline = onlineeps[selectedSeries];
  161. fillEpGrid(selectedSeriesListLocal, selectedSeriesListOnline);
  162. // set the available sort options
  163. this.comboMatchOptions.Items.Clear();
  164. foreach (var ordering in selectedSeries[DBOnlineSeries.cEpisodeOrders].ToString().Split(new char[]{'|'}, StringSplitOptions.RemoveEmptyEntries))
  165. {
  166. comboMatchOptions.Items.Add(ordering);
  167. }
  168. // Always add 'Aired' as a match option
  169. if (comboMatchOptions.Items.Count == 0) comboMatchOptions.Items.Add("Aired");
  170. // 'Title' can also be matched against so add that
  171. comboMatchOptions.Items.Add("Title");
  172. string preChosen = selectedSeries[DBOnlineSeries.cChosenEpisodeOrder];
  173. if (string.IsNullOrEmpty(preChosen))
  174. comboMatchOptions.SelectedIndex = 0;
  175. else comboMatchOptions.SelectedItem = preChosen;
  176. }
  177. private string getDisplayString(DBTable ep)
  178. {
  179. if (ep is DBEpisode)
  180. {
  181. return string.Format("{0,2:D}x{1,2:D}{2} {3}",
  182. ep[DBEpisode.cSeasonIndex],
  183. ep[DBEpisode.cEpisodeIndex] > 0 ? (string)ep[DBEpisode.cEpisodeIndex] : "?",
  184. ep[DBEpisode.cEpisodeIndex2] > 0 ? "-" + ep[DBEpisode.cEpisodeIndex2] : string.Empty,
  185. ep[DBEpisode.cEpisodeName].ToString());
  186. }
  187. else if (ep is DBOnlineEpisode)
  188. {
  189. return string.Format("{0,2:D}{1,2:D}{2} - {3} [{4}]",
  190. ep[DBEpisode.cSeasonIndex] > 0 ? (string)ep[DBEpisode.cSeasonIndex] + "x" : "Special: ",
  191. ep[DBEpisode.cEpisodeIndex] > 0 ? (string)ep[DBEpisode.cEpisodeIndex] : "?",
  192. ep[DBEpisode.cEpisodeIndex2] > 0 ? "-" + ep[DBEpisode.cEpisodeIndex2] : string.Empty,
  193. ep[DBOnlineEpisode.cEpisodeName], ep[DBOnlineEpisode.cFirstAired]);
  194. }
  195. return string.Empty;
  196. }
  197. private void fillEpGrid(List<DBEpisode> localEps, List<DBOnlineEpisode> onlineEps)
  198. {
  199. listBoxLocal.Items.Clear();
  200. listBoxOnline.Items.Clear();
  201. displayedEps.Clear();
  202. displayedOEps.Clear();
  203. displayedOEps.Add(null);
  204. listBoxOnline.Items.Add("No Match");
  205. foreach (var online in onlineEps)
  206. {
  207. displayedOEps.Add(online);
  208. listBoxOnline.Items.Add(getDisplayString(online));
  209. }
  210. foreach (var local in localEps.OrderBy( e => e[DBEpisode.cSeasonIndex] * 100 + e[DBEpisode.cEpisodeIndex]))
  211. {
  212. if (checkBoxFilter.Checked)
  213. {
  214. // only display those we couldnt match
  215. var pair = matches.Single(s => s.Key == listBoxSeries.SelectedItem as DBSeries).Value.SingleOrDefault(e => e.Key == local);
  216. if (pair.Value != null)
  217. continue;
  218. }
  219. displayedEps.Add(local);
  220. listBoxLocal.Items.Add(local[DBEpisode.cFilenameWOPath]);
  221. //listBoxLocal.Items.Add(getDisplayString(local));
  222. }
  223. if (listBoxLocal.SelectedIndex < 0 && listBoxLocal.Items.Count > 0)
  224. listBoxLocal.SelectedIndex = 0;
  225. }
  226. private void listBoxLocal_SelectedIndexChanged(object sender, EventArgs e)
  227. {
  228. var series = listBoxSeries.SelectedItem as DBSeries;
  229. var localEp = displayedEps[listBoxLocal.SelectedIndex];
  230. var matchedOnlineEp = matches.Single(s => s.Key == series).Value.Single(eps => eps.Key == localEp).Value;
  231. string selectedItem = string.Empty;
  232. if (matchedOnlineEp != null)
  233. listBoxOnline.SelectedItem = getDisplayString(matchedOnlineEp);
  234. else listBoxOnline.SelectedIndex = 0;
  235. txtBoxStatusBar.Text = localEp[DBEpisode.cFilename];
  236. }
  237. private void listBoxOnline_SelectedIndexChanged(object sender, EventArgs e)
  238. {
  239. if (listBoxLocal.SelectedIndex < 0) return; // maybe already matched all local
  240. var series = listBoxSeries.SelectedItem as DBSeries;
  241. var localEp = displayedEps[listBoxLocal.SelectedIndex];
  242. var onlineEp = displayedOEps[listBoxOnline.SelectedIndex];
  243. // update the pair
  244. var pairS = matches.Single(s => s.Key == series).Value;
  245. int toReplace = pairS.FindIndex(kv => kv.Key == localEp);
  246. pairS[toReplace] = new KeyValuePair<DBEpisode, DBOnlineEpisode>(localEp, onlineEp);
  247. }
  248. private void checkBoxFilter_CheckedChanged(object sender, EventArgs e)
  249. {
  250. txtBoxStatusBar.Text = string.Empty;
  251. FillSeriesList();
  252. }
  253. private void buttonMatchAgain_Click(object sender, EventArgs e)
  254. {
  255. string selected = comboMatchOptions.SelectedItem.ToString();
  256. DBSeries series = listBoxSeries.SelectedItem as DBSeries;
  257. series[DBOnlineSeries.cChosenEpisodeOrder] = selected;
  258. // default sort order should correspond to the chosen episode order
  259. series[DBOnlineSeries.cEpisodeSortOrder] = selected == "DVD" ? "DVD" : "Aired";
  260. series.Commit();
  261. DoAutoMatching(series, selected);
  262. listBoxSeries_SelectedIndexChanged(listBoxSeries, null);
  263. comboMatchOptions.SelectedItem = selected;
  264. }
  265. }
  266. }