OSDN Git Service

34e2cddf30dc67a295bb103248b6a4544becad0d
[handbrake-jp/handbrake-jp-git.git] / win / C# / Controls / Subtitles.cs
1 /*  Subtitles.cs $\r
2         \r
3            This file is part of the HandBrake source code.\r
4            Homepage: <http://handbrake.fr>.\r
5            It may be used under the terms of the GNU General Public License. */\r
6 \r
7 using System;\r
8 using System.Collections.Generic;\r
9 using System.IO;\r
10 using System.Windows.Forms;\r
11 using Handbrake.Functions;\r
12 using Handbrake.Model;\r
13 \r
14 namespace Handbrake.Controls\r
15 {\r
16     using System.Linq;\r
17 \r
18     public partial class Subtitles : UserControl\r
19     {\r
20         readonly IDictionary<string, string> langMap = new Dictionary<string, string>();\r
21         readonly List<SubtitleInfo> subList = new List<SubtitleInfo>();\r
22         private int fileContainer;\r
23 \r
24         public Subtitles()\r
25         {\r
26             InitializeComponent();\r
27 \r
28             langMap = Main.MapLanguages();\r
29             foreach (string key in langMap.Keys)\r
30                 srt_lang.Items.Add(key);\r
31 \r
32             srt_charcode.SelectedIndex = 28;\r
33             srt_lang.SelectedIndex = 40;\r
34         }\r
35 \r
36         // Primary Controls\r
37         private void BtnAddSubTrackClick(object sender, EventArgs e)\r
38         {\r
39             // Logic\r
40             string forcedVal = check_forced.CheckState == CheckState.Checked ? "Yes" : "No";\r
41             string defaultSub = check_default.CheckState == CheckState.Checked ? "Yes" : "No";\r
42             string burnedVal = check_burned.CheckState == CheckState.Checked && (!drp_subtitleTracks.Text.Contains("Text")) ? "Yes" : "No";\r
43             string srtCode = "-", srtLangVal = "-", srtPath = "-", srtFile = "-";\r
44             int srtOffsetMs = 0;\r
45 \r
46             if (drp_subtitleTracks.SelectedItem.ToString().Contains(".srt"))\r
47             {\r
48                 burnedVal = "No";\r
49                 forcedVal = "No";\r
50                 srtPath = openFileDialog.FileName;\r
51                 srtFile = Path.GetFileName(openFileDialog.FileName);\r
52                 srtLangVal = srt_lang.SelectedItem.ToString();\r
53                 srtCode = srt_charcode.SelectedItem.ToString();\r
54                 srtOffsetMs = (int)srt_offset.Value;\r
55                 if (defaultSub == "Yes") SetNoSrtDefault();\r
56             } else\r
57             {\r
58                 if (defaultSub == "Yes") SetNoDefault();\r
59                 if (burnedVal == "Yes") SetNoBurned();\r
60 \r
61                 if (fileContainer == 0)\r
62                     burnedVal = "Yes";  // MP4 must have bitmap subs burned in.\r
63             }\r
64 \r
65             if (fileContainer == 0) // MP4 and M4V file extension\r
66             {\r
67                 // Make sure we only have 1 bitmap track.\r
68                 if (drp_subtitleTracks.SelectedItem != null && drp_subtitleTracks.SelectedItem.ToString().Contains("Bitmap"))\r
69                 {\r
70                     if (lv_subList.Items.Cast<ListViewItem>().Any(item => item.SubItems[0].Text.Contains("Bitmap")))\r
71                     {\r
72                         MessageBox.Show(this, "More than one vobsub is not supported in mp4... Your first vobsub track will now be used.",\r
73                                         "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
74                         return;\r
75                     }\r
76                 }\r
77             }\r
78 \r
79             string trackName = (drp_subtitleTracks.SelectedItem.ToString().Contains(".srt"))\r
80                                ? srtLangVal + " (" + srtFile + ")"\r
81                                : drp_subtitleTracks.SelectedItem.ToString();\r
82 \r
83 \r
84             SubtitleInfo track = new SubtitleInfo\r
85                                      {\r
86                                          Track = trackName,\r
87                                          Forced = forcedVal,\r
88                                          Burned = burnedVal,\r
89                                          Default = defaultSub,\r
90                                          SrtLang = srtLangVal,\r
91                                          SrtCharCode = srtCode,\r
92                                          SrtOffset = srtOffsetMs,\r
93                                          SrtPath = srtPath,\r
94                                          SrtFileName = srtFile\r
95                                      };\r
96 \r
97             lv_subList.Items.Add(track.ListView);\r
98             subList.Add(track);\r
99 \r
100         }\r
101         private void BtnSrtAddClick(object sender, EventArgs e)\r
102         {\r
103             if (openFileDialog.ShowDialog() != DialogResult.OK)\r
104                 return;\r
105             drp_subtitleTracks.Items.Add(Path.GetFileName(openFileDialog.FileName));\r
106             drp_subtitleTracks.SelectedItem = Path.GetFileName(openFileDialog.FileName);\r
107         }\r
108         private void BtnRemoveSubTrackClick(object sender, EventArgs e)\r
109         {\r
110             RemoveTrack();\r
111         }\r
112 \r
113         // Secondary Controls\r
114         private void LbSubListSelectedIndexChanged(object sender, EventArgs e)\r
115         {\r
116             // Set the dropdown controls based on the selected item in the List.\r
117             if (lv_subList.Items.Count != 0 && lv_subList.SelectedIndices.Count != 0)\r
118             {\r
119                 SubtitleInfo track = subList[lv_subList.SelectedIndices[0]];\r
120 \r
121                 int c = 0;\r
122                 if (lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text.ToLower().Contains(".srt"))  // We have an SRT\r
123                 {\r
124                     foreach (var item in drp_subtitleTracks.Items)\r
125                     {\r
126                         if (item.ToString() == track.SrtFileName)\r
127                             drp_subtitleTracks.SelectedIndex = c;\r
128                         c++;\r
129                     }\r
130                     srt_lang.SelectedItem = track.SrtLang;\r
131                     srt_offset.Value = track.SrtOffset;\r
132                     srt_charcode.SelectedItem = track.SrtCharCode;\r
133                     check_default.CheckState = track.Default == "Yes" ? CheckState.Checked : CheckState.Unchecked;\r
134                     SubGroupBox.Text = "Selected Track: " + track.Track;\r
135                 }\r
136                 else  // We have Bitmap/CC\r
137                 {\r
138                     foreach (var item in drp_subtitleTracks.Items)\r
139                     {\r
140                         if (item.ToString() == track.Track)\r
141                             drp_subtitleTracks.SelectedIndex = c;\r
142                         c++;\r
143                     }\r
144                     check_forced.CheckState = track.Forced == "Yes" ? CheckState.Checked : CheckState.Unchecked;\r
145                     check_burned.CheckState = track.Burned == "Yes" ? CheckState.Checked : CheckState.Unchecked;\r
146                     check_default.CheckState = track.Default == "Yes" ? CheckState.Checked : CheckState.Unchecked;\r
147                     SubGroupBox.Text = "Selected Track: " + lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text;\r
148                 }\r
149             }\r
150             else\r
151                 SubGroupBox.Text = "Selected Track: None (Click \"Add\" to add another track to the list)";\r
152         }\r
153 \r
154         // Bitmap / CC / SRT Controls\r
155         private void DrpSubtitleTracksSelectedIndexChanged(object sender, EventArgs e)\r
156         {\r
157             if (drp_subtitleTracks.SelectedItem.ToString().Contains(".srt"))\r
158             {\r
159                 check_forced.Enabled = false;\r
160                 check_burned.Enabled = false;\r
161                 srt_lang.Enabled = true;\r
162                 srt_charcode.Enabled = true;\r
163                 srt_offset.Enabled = true;\r
164             }\r
165             else\r
166             {\r
167                 check_forced.Enabled = true;\r
168                 check_burned.Enabled = true;\r
169                 srt_lang.Enabled = false;\r
170                 srt_charcode.Enabled = false;\r
171                 srt_offset.Enabled = false;\r
172             }\r
173             // Update an item in the  list if required.\r
174             if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;\r
175 \r
176             if (drp_subtitleTracks.SelectedItem.ToString().Contains(".srt"))\r
177             {\r
178                 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text = srt_lang.SelectedItem + "(" +\r
179                     drp_subtitleTracks.SelectedItem + ")";\r
180                 lv_subList.Select();\r
181             } else\r
182             {\r
183                 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text =\r
184                     drp_subtitleTracks.SelectedItem.ToString();\r
185                 lv_subList.Select();\r
186             }\r
187 \r
188             subList[lv_subList.SelectedIndices[0]].Track = drp_subtitleTracks.SelectedItem.ToString(); // Update SubList List<SubtitleInfo>\r
189         }\r
190         private void CheckForcedCheckedChanged(object sender, EventArgs e)\r
191         {\r
192             if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;\r
193 \r
194             lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[1].Text = check_forced.Checked ? "Yes" : "No";\r
195             lv_subList.Select();\r
196 \r
197             subList[lv_subList.SelectedIndices[0]].Forced = check_forced.Checked ? "Yes" : "No"; // Update SubList List<SubtitleInfo> \r
198         }\r
199         private void CheckBurnedCheckedChanged(object sender, EventArgs e)\r
200         {\r
201             if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;\r
202 \r
203             if (check_burned.Checked) // Make sure we only have 1 burned track\r
204                 SetNoBurned();\r
205 \r
206             lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[2].Text = check_burned.Checked ? "Yes" : "No";\r
207             lv_subList.Select();\r
208 \r
209             subList[lv_subList.SelectedIndices[0]].Burned = check_burned.Checked ? "Yes" : "No"; // Update SubList List<SubtitleInfo> \r
210         }\r
211         private void CheckDefaultCheckedChanged(object sender, EventArgs e)\r
212         {\r
213             if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;\r
214 \r
215             if (check_default.Checked) // Make sure we only have 1 default track\r
216                 if (lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text.Contains(".srt"))\r
217                     SetNoSrtDefault();\r
218                 else\r
219                     SetNoDefault();\r
220 \r
221             lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[3].Text = check_default.Checked ? "Yes" : "No";\r
222             lv_subList.Select();\r
223 \r
224             subList[lv_subList.SelectedIndices[0]].Default = check_default.Checked ? "Yes" : "No"; // Update SubList List<SubtitleInfo>\r
225         }\r
226         private void SrtOffsetValueChanged(object sender, EventArgs e)\r
227         {\r
228             // Update an item in the  list if required.\r
229             if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0)\r
230                 return;\r
231 \r
232             lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[6].Text = srt_offset.Value.ToString();\r
233             lv_subList.Select();\r
234 \r
235             subList[lv_subList.SelectedIndices[0]].SrtOffset = (int)srt_offset.Value; // Update SubList List<SubtitleInfo>\r
236         }\r
237         private void SrtCharcodeSelectedIndexChanged(object sender, EventArgs e)\r
238         {\r
239             if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;\r
240 \r
241             lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[5].Text = srt_charcode.SelectedItem.ToString();\r
242             lv_subList.Select();\r
243 \r
244             subList[lv_subList.SelectedIndices[0]].SrtCharCode = srt_charcode.SelectedItem.ToString(); // Update SubList List<SubtitleInfo>\r
245         }\r
246         private void SrtLangSelectedIndexChanged(object sender, EventArgs e)\r
247         {\r
248             if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;\r
249 \r
250             lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[4].Text = srt_lang.SelectedItem.ToString();\r
251             lv_subList.Select();\r
252 \r
253             subList[lv_subList.SelectedIndices[0]].SrtLang = srt_lang.SelectedItem.ToString(); // Update SubList List<SubtitleInfo>\r
254         }\r
255 \r
256         // Right Click Menu\r
257         private void MnuMoveupClick(object sender, EventArgs e)\r
258         {\r
259             if (lv_subList.SelectedIndices.Count != 0)\r
260             {\r
261                 ListViewItem item = lv_subList.SelectedItems[0];\r
262                 int index = item.Index;\r
263                 index--;\r
264 \r
265                 if (lv_subList.Items.Count > index && index >= 0)\r
266                 {\r
267                     lv_subList.Items.Remove(item);\r
268                     lv_subList.Items.Insert(index, item);\r
269                     item.Selected = true;\r
270                     lv_subList.Focus();\r
271                 }\r
272             }\r
273         }\r
274         private void MnuMovedownClick(object sender, EventArgs e)\r
275         {\r
276             if (lv_subList.SelectedIndices.Count != 0)\r
277             {\r
278                 ListViewItem item = lv_subList.SelectedItems[0];\r
279                 int index = item.Index;\r
280                 index++;\r
281 \r
282                 if (index < lv_subList.Items.Count)\r
283                 {\r
284                     lv_subList.Items.Remove(item);\r
285                     lv_subList.Items.Insert(index, item);\r
286                     item.Selected = true;\r
287                     lv_subList.Focus();\r
288                 }\r
289             }\r
290         }\r
291         private void MnuRemoveClick(object sender, EventArgs e)\r
292         {\r
293             RemoveTrack();\r
294         }\r
295 \r
296         // Functions\r
297         private void SetNoDefault()\r
298         {\r
299             int c = 0;\r
300             foreach (ListViewItem item in lv_subList.Items)\r
301             {\r
302                 if (subList[c].SrtPath == "-")\r
303                 {\r
304                     if (item.SubItems[3].Text == "Yes")\r
305                     {\r
306                         item.SubItems[3].Text = "No";\r
307                         subList[c].Default = "No";\r
308                     }     \r
309                 }\r
310                 c++;\r
311             }\r
312         }\r
313 \r
314         /// <summary>\r
315         /// Set all subtitle tracks so that they have no default.\r
316         /// </summary>\r
317         private void SetNoSrtDefault()\r
318         {\r
319             int c = 0;\r
320             foreach (ListViewItem item in lv_subList.Items)\r
321             {\r
322                 if (!subList[c].IsSrtSubtitle)\r
323                 {\r
324                     if (item.SubItems[3].Text == "Yes")\r
325                     {\r
326                         item.SubItems[3].Text = "No";\r
327                         subList[c].Default = "No";\r
328                     }\r
329                 }\r
330                 c++;\r
331             }\r
332         }\r
333         private void SetNoBurned()\r
334         {\r
335             int c = 0;\r
336             foreach (ListViewItem item in lv_subList.Items)\r
337             {\r
338                 if (item.SubItems[2].Text == "Yes")\r
339                 {\r
340                     item.SubItems[2].Text = "No";\r
341                     subList[c].Burned = "No";\r
342                 }\r
343                 c++;\r
344             }\r
345         }\r
346         private void RemoveTrack()\r
347         {\r
348             // Remove the Item and reselect the control if the following conditions are met.\r
349             if (lv_subList.SelectedItems.Count != 0)\r
350             {\r
351                 // Record the current selected index.\r
352                 int currentPosition = lv_subList.SelectedIndices[0];\r
353                 int selectedInd = lv_subList.SelectedIndices[0];\r
354 \r
355                 lv_subList.Items.RemoveAt(selectedInd);\r
356                 subList.RemoveAt(selectedInd);\r
357 \r
358                 // Now reslect the correct item and give focus to the list.\r
359                 if (lv_subList.Items.Count != 0)\r
360                 {\r
361                     if (currentPosition <= (lv_subList.Items.Count - 1))\r
362                         lv_subList.Items[currentPosition].Selected = true;\r
363                     else if (currentPosition > (lv_subList.Items.Count - 1))\r
364                         lv_subList.Items[lv_subList.Items.Count - 1].Selected = true;\r
365 \r
366                     lv_subList.Select();\r
367                 }\r
368             }\r
369         }\r
370 \r
371         /// <summary>\r
372         /// Clear the Subtitle List\r
373         /// </summary>\r
374         public void Clear()\r
375         {\r
376             lv_subList.Items.Clear();\r
377             subList.Clear();\r
378         }\r
379 \r
380         /// <summary>\r
381         /// Cleverly Clear the subtitle list. Only remove tracks that are not available for the current source.\r
382         /// </summary>\r
383         public void SmartClear()\r
384         {\r
385             /* Smart clear will only remove subtitle tracks that do not have an equivlent \r
386               for the new source / title which the user has selected. */\r
387             throw new NotImplementedException();\r
388         }\r
389 \r
390         /// <summary>\r
391         /// Checks of the current settings will require the m4v file extension\r
392         /// </summary>\r
393         /// <returns>True if Yes</returns>\r
394         public Boolean RequiresM4V()\r
395         {\r
396             foreach (ListViewItem item in lv_subList.Items)\r
397             {\r
398                 if (item.SubItems.Count != 5)\r
399                     return true;\r
400 \r
401                 if (item.SubItems[1].Text.Contains("(Text)"))\r
402                     return true;\r
403             }\r
404             return false;\r
405         }\r
406 \r
407         /// <summary>\r
408         /// Automatically setup the subtitle tracks.\r
409         /// This handles the automatic setup of subitles which the user can control from the program options\r
410         /// </summary>\r
411         /// <param name="subs"></param>\r
412         public void SetSubtitleTrackAuto(object[] subs)\r
413         {\r
414             drp_subtitleTracks.Items.Clear();\r
415             drp_subtitleTracks.Items.Add("Foreign Audio Search (Bitmap)");\r
416             drp_subtitleTracks.Items.AddRange(subs);\r
417             drp_subtitleTracks.SelectedIndex = 0;\r
418             Clear();\r
419 \r
420             // Handle Native Language and "Dub Foreign language audio" and "Use Foreign language audio and Subtitles" Options\r
421             if (Properties.Settings.Default.NativeLanguage != "Any")\r
422             {\r
423                 if (!Properties.Settings.Default.DubAudio) // We need to add a subtitle track if this is false.\r
424                 {\r
425                     int i = 0;\r
426                     foreach (object item in drp_subtitleTracks.Items)\r
427                     {\r
428                         if (item.ToString().Contains(Properties.Settings.Default.NativeLanguage))\r
429                             drp_subtitleTracks.SelectedIndex = i;\r
430 \r
431                         i++;\r
432                     }\r
433 \r
434                     BtnAddSubTrackClick(this, new EventArgs());\r
435                 }\r
436             }\r
437         }\r
438 \r
439         /// <summary>\r
440         /// Set the file container which is currently in use.\r
441         /// </summary>\r
442         /// <param name="value"></param>\r
443         public void SetContainer(int value)\r
444         {\r
445             fileContainer = value;\r
446             Boolean trigger = false;\r
447             if (fileContainer != 1)\r
448                 foreach (ListViewItem item in lv_subList.Items)\r
449                 {\r
450                     if (item.SubItems[1].Text.Contains("Bitmap"))\r
451                     {\r
452                         if (trigger)\r
453                             lv_subList.Items.Remove(item);\r
454                         trigger = true;\r
455                     }\r
456                 }\r
457         }\r
458 \r
459         /// <summary>\r
460         /// Get the list of subtitles.\r
461         /// </summary>\r
462         /// <returns></returns>\r
463         public List<SubtitleInfo> GetSubtitleInfoList()\r
464         {\r
465             return subList;\r
466         }\r
467 \r
468         /// <summary>\r
469         /// Get the CLI Query for this panel\r
470         /// </summary>\r
471         /// <returns></returns>\r
472         public string GetCliQuery\r
473         {\r
474             get\r
475             {\r
476                 string query = string.Empty;\r
477                 if (lv_subList.Items.Count != 0) // If we have subtitle tracks\r
478                 {\r
479                     // BitMap and CC's\r
480                     string subtitleTracks = String.Empty;\r
481                     string subtitleForced = String.Empty;\r
482                     string subtitleBurn = String.Empty;\r
483                     string subtitleDefault = String.Empty;\r
484 \r
485                     // SRT\r
486                     string srtFile = String.Empty;\r
487                     string srtCodeset = String.Empty;\r
488                     string srtOffset = String.Empty;\r
489                     string srtLang = String.Empty;\r
490                     string srtDefault = String.Empty;\r
491                     int srtCount = 0;\r
492 \r
493                     foreach (SubtitleInfo item in subList)\r
494                     {\r
495                         string itemToAdd, trackId;\r
496 \r
497                         if (item.IsSrtSubtitle) // We have an SRT file\r
498                         {\r
499                             srtCount++; // SRT track id.\r
500 \r
501                             srtLang += srtLang == "" ? langMap[item.SrtLang] : "," + langMap[item.SrtLang];\r
502                             srtCodeset += srtCodeset == "" ? item.SrtCharCode : "," + item.SrtCharCode;\r
503 \r
504                             if (item.Default == "Yes")\r
505                                 srtDefault = srtCount.ToString();\r
506 \r
507                             itemToAdd = item.SrtPath;\r
508                             srtFile += srtFile == "" ? itemToAdd : "," + itemToAdd;\r
509 \r
510                             itemToAdd = item.SrtOffset.ToString();\r
511                             srtOffset += srtOffset == "" ? itemToAdd : "," + itemToAdd;\r
512                         }\r
513                         else // We have Bitmap or CC\r
514                         {\r
515                             string[] tempSub;\r
516 \r
517                             // Find --subtitle <string>\r
518                             if (item.Track.Contains("Foreign Audio Search"))\r
519                                 itemToAdd = "scan";\r
520                             else\r
521                             {\r
522                                 tempSub = item.Track.Split(' ');\r
523                                 itemToAdd = tempSub[0];\r
524                             }\r
525 \r
526                             subtitleTracks += subtitleTracks == "" ? itemToAdd : "," + itemToAdd;\r
527 \r
528                             // Find --subtitle-forced\r
529                             itemToAdd = "";\r
530                             tempSub = item.Track.Split(' ');\r
531                             trackId = tempSub[0];\r
532 \r
533                             if (item.Forced == "Yes")\r
534                                 itemToAdd = "scan";\r
535 \r
536                             if (itemToAdd != "")\r
537                                 subtitleForced += subtitleForced == "" ? itemToAdd : "," + itemToAdd;\r
538 \r
539                             // Find --subtitle-burn and --subtitle-default\r
540                             trackId = tempSub[0];\r
541 \r
542                             if (trackId.Trim() == "Foreign") // foreign audio search\r
543                                 trackId = "scan";\r
544 \r
545                             if (item.Burned == "Yes") // burn\r
546                                 subtitleBurn = trackId;\r
547 \r
548                             if (item.Default == "Yes") // default\r
549                                 subtitleDefault = trackId;\r
550                         }\r
551                     }\r
552 \r
553                     // Build The CLI Subtitles Query\r
554                     if (subtitleTracks != "")\r
555                     {\r
556                         query += " --subtitle " + subtitleTracks;\r
557 \r
558                         if (subtitleForced != "")\r
559                             query += " --subtitle-forced=" + subtitleForced;\r
560                         if (subtitleBurn != "")\r
561                             query += " --subtitle-burn=" + subtitleBurn;\r
562                         if (subtitleDefault != "")\r
563                             query += " --subtitle-default=" + subtitleDefault;\r
564                     }\r
565 \r
566                     if (srtFile != "") // SRTs\r
567                     {\r
568                         query += " --srt-file " + "\"" + srtFile + "\"";\r
569 \r
570                         if (srtCodeset != "")\r
571                             query += " --srt-codeset " + srtCodeset;\r
572                         if (srtOffset != "")\r
573                             query += " --srt-offset " + srtOffset;\r
574                         if (srtLang != "")\r
575                             query += " --srt-lang " + srtLang;\r
576                         if (srtDefault != "")\r
577                             query += " --srt-default=" + srtDefault;\r
578                     }\r
579 \r
580                 }\r
581                 return query;\r
582             }\r
583         }\r
584     }\r
585 }