99using System . Linq ;
1010using System . Text ;
1111using System . Text . RegularExpressions ;
12+ using System . Threading . Tasks ;
1213using System . Windows . Forms ;
1314
1415namespace SubtitleRenamer
1516{
1617 public partial class MainForm
1718 {
1819 private static string OpenPath = "" ;
20+ private static bool isFilesLoading = false ;
1921 private static List < FileInfo > VideoFileList = new List < FileInfo > { } ;
2022 private static List < FileInfo > SubtitleFileList = new List < FileInfo > { } ;
2123
@@ -26,10 +28,48 @@ public partial class MainForm
2628 private static Dictionary < string , string > SubtitleEpisDict = new Dictionary < string , string > { } ;
2729
2830 private static Dictionary < string , string > SubtitleRenameDict = new Dictionary < string , string > { } ; // 之前文件名 -> 修改后文件名
31+ private static Dictionary < string , string > SubtitleChangedStatus = new Dictionary < string , string > { } ; // 已经修改了文件名的字幕(原始文件名)
2932
30- private void ReloadFiles ( )
33+ private static string CurtStatus = "" ;
34+ private void SetCurtStatus ( string status )
35+ {
36+ CurtStatus = status . Trim ( ) ;
37+ RefreshFileListBox ( ) ;
38+ }
39+
40+ private static FileSystemWatcher OpenPathWatcher = null ;
41+
42+ // 实时检测 OpenPath 文件变化,并重载文件列表
43+ private void OpenPathWatcherRestart ( )
44+ {
45+ if ( OpenPathWatcher == null )
46+ {
47+ OpenPathWatcher = new FileSystemWatcher ( ) ;
48+ OpenPathWatcher . Created += OpenPathFileChanged ;
49+ OpenPathWatcher . Deleted += OpenPathFileChanged ;
50+ OpenPathWatcher . Renamed += OpenPathFileChanged ;
51+ }
52+
53+ OpenPathWatcher . Path = OpenPath ;
54+ OpenPathWatcher . EnableRaisingEvents = false ;
55+ }
56+
57+ private void OpenPathFileChanged ( object sender , FileSystemEventArgs e )
58+ {
59+ ReloadFiles ( ) ;
60+ }
61+
62+ // 重新加载 OpenPath 中的文件
63+ protected void ReloadFiles ( ) => Task . Factory . StartNew ( ( ) => _ReloadFiles ( ) ) ;
64+
65+ private void _ReloadFiles ( )
3166 {
3267 if ( OpenPath == null || OpenPath . Trim ( ) == "" ) return ;
68+ // 显示加载中...
69+ isFilesLoading = true ;
70+ CurtStatus = "" ;
71+ RefreshFileListBox ( ) ;
72+ OpenPathWatcherRestart ( ) ;
3373
3474 var folder = new DirectoryInfo ( OpenPath ) ;
3575 var files = folder . GetFiles ( "*" ) ;
@@ -46,49 +86,86 @@ private void ReloadFiles()
4686
4787 // 清空历史数据
4888 SubtitleRenameDict . Clear ( ) ;
89+ SubtitleChangedStatus . Clear ( ) ;
4990 VideoEpisDict . Clear ( ) ;
5091 SubtitleEpisDict . Clear ( ) ;
5192
5293 // 刷新文件列表
94+ isFilesLoading = false ;
5395 RefreshFileListBox ( ) ;
96+
97+ // 处理文件
98+ MatchEpisode ( ) ;
99+
100+ // 启动 OpenPath 实时监测,刷新列表
101+ OpenPathWatcher . EnableRaisingEvents = true ;
54102 }
55103
56- private void RefreshFileListBox ( )
104+ private void RefreshFileListBox ( ) => BeginInvoke ( ( MethodInvoker ) delegate
105+ {
106+ _RefreshFileListBox ( ) ;
107+ } ) ;
108+
109+ private void _RefreshFileListBox ( )
57110 {
58- // 字幕 listBox
59111 SubtitleFileListBox . Items . Clear ( ) ;
112+ VideoFileListBox . Items . Clear ( ) ;
113+
114+ // Head
115+ SubtitleFileListBox . Items . Add ( $ " ◈ 字幕文件 - { SubtitleFileList . Count } 个项目 { ( ! CurtStatus . Equals ( "" ) ? $ "[{ CurtStatus } ]" : "" ) } ") ;
116+ VideoFileListBox . Items . Add ( $ " ◈ 视频文件 - { VideoFileList . Count } 个项目") ;
117+
118+ // Loading
119+ if ( isFilesLoading )
120+ {
121+ SubtitleFileListBox . Items . Add ( " 加载中..." ) ;
122+ VideoFileListBox . Items . Add ( " 加载中..." ) ;
123+ return ;
124+ }
125+
126+ // 字幕文件
60127 foreach ( var file in SubtitleFileList )
61128 {
62- var str = "" ;
129+ var str = " " ;
63130 if ( SubtitleEpisDict . ContainsKey ( file . Name ) )
64131 str += $ "[集数:{ SubtitleEpisDict [ file . Name ] } ] ";
65132 str += file . Name ;
66133 SubtitleFileListBox . Items . Add ( str ) ;
67134 if ( SubtitleRenameDict . ContainsKey ( file . Name ) )
68135 {
69- SubtitleFileListBox . Items . Add ( String . Format ( "{0,12}" , " => " ) + SubtitleRenameDict [ file . Name ] ) ;
136+ string renameStatus = SubtitleChangedStatus . ContainsKey ( file . Name ) ? SubtitleChangedStatus [ file . Name ] : "" ;
137+ SubtitleFileListBox . Items . Add ( String . Format ( "{0,17}" , renameStatus + " => " ) + SubtitleRenameDict [ file . Name ] ) ;
70138 }
71139 }
72140
73- // 视频 listBox
74- VideoFileListBox . Items . Clear ( ) ;
141+ // 视频文件
75142 foreach ( var file in VideoFileList )
76143 {
77- var str = "" ;
144+ var str = " " ;
78145 if ( VideoEpisDict . ContainsKey ( file . Name ) )
79146 str += $ "[集数:{ VideoEpisDict [ file . Name ] } ] ";
80147 str += file . Name ;
81148 VideoFileListBox . Items . Add ( str ) ;
82149 }
83150 }
84151
152+ protected void MatchEpisode ( ) => Task . Factory . StartNew ( ( ) => _MatchEpisode ( ) ) ;
153+
85154 // 匹配 视频 & 字幕 集数位置
86- private void MatchEpisode ( )
155+ private void _MatchEpisode ( )
87156 {
88- int beginPos = GetEpisodePosByTwoStr ( VideoFileList [ 0 ] . Name , VideoFileList [ 1 ] . Name ) ; // 视频文件名集数开始位置
89- int subBeginPos = GetEpisodePosByTwoStr ( SubtitleFileList [ 0 ] . Name , SubtitleFileList [ 1 ] . Name ) ; // 字幕文件名集数开始位置
157+ if ( VideoFileList . Count < 2 || SubtitleFileList . Count < 2 ) return ;
158+
159+ SetCurtStatus ( "匹配集数中..." ) ;
90160
91- if ( beginPos <= - 1 || subBeginPos <= - 1 )
161+ int beginPos ;
162+ int subBeginPos ;
163+ try
164+ {
165+ beginPos = GetEpisodePosByTwoStr ( VideoFileList [ 0 ] . Name , VideoFileList [ 1 ] . Name ) ; // 视频文件名集数开始位置
166+ subBeginPos = GetEpisodePosByTwoStr ( SubtitleFileList [ 0 ] . Name , SubtitleFileList [ 1 ] . Name ) ; // 字幕文件名集数开始位置
167+ }
168+ catch
92169 {
93170 MessageBox . Show ( "无法正确匹配集数位置,需进一步手动确认" , "错误" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
94171 return ;
@@ -121,6 +198,7 @@ private void MatchEpisode()
121198 }
122199
123200 // 刷新文件列表
201+ SetCurtStatus ( "集数已匹配" ) ;
124202 RefreshFileListBox ( ) ;
125203 }
126204
@@ -143,25 +221,101 @@ private int GetEpisodePosByTwoStr(string strA, string strB)
143221 }
144222 }
145223
224+ if ( beginPos == - 1 )
225+ {
226+ throw new Exception ( "beginPos == -1" ) ;
227+ }
228+
146229 return beginPos ;
147230 }
148231
149232 /// 获取集数
150233 private string GetEpisByFileName ( string fileName , int beginPos )
151234 {
152235 if ( beginPos <= - 1 )
153- {
154236 return null ;
155- }
156237
157238 var str = fileName . Substring ( beginPos ) ;
158- return Regex . Matches ( str , @"(\d+)" ) [ 0 ] . Value ; // 为了获得完整的数字,无论多少位
239+ var grp = Regex . Matches ( str , @"(\d+)" ) ;
240+ return ( grp . Count >= 1 ) ? grp [ 0 ] . Value : null ; // 为了获得完整的数字,无论多少位
159241 }
160242
243+ protected void StartRename ( ) => Task . Factory . StartNew ( ( ) => _StartRename ( ) ) ;
244+
161245 /// 执行改名操作
162- private void StartRename ( )
246+ private void _StartRename ( )
163247 {
164- MessageBox . Show ( "修改文件名代码还没写... 睡觉了..." ) ;
248+ OpenPathWatcher . EnableRaisingEvents = false ; // 暂时关闭目录变化列表实时更新
249+ SubtitleChangedStatus . Clear ( ) ;
250+
251+ foreach ( var item in SubtitleRenameDict )
252+ {
253+ string before = item . Key ;
254+ string after = item . Value ;
255+ string beforeFullPath = Path . Combine ( OpenPath , before ) ;
256+ string afterFullPath = Path . Combine ( OpenPath , after ) ;
257+
258+ SubtitleChangedStatus [ before ] = "更名中" ;
259+ RefreshFileListBox ( ) ;
260+
261+ // 无需更名
262+ if ( before . Equals ( after ) || SubtitleChangedStatus [ before ] == "✔" )
263+ {
264+ SubtitleChangedStatus [ before ] = "✔" ;
265+ continue ;
266+ }
267+
268+ // 原文件是否存在
269+ if ( ! File . Exists ( beforeFullPath ) )
270+ {
271+ SubtitleChangedStatus [ before ] = "✖" ;
272+ continue ;
273+ }
274+
275+ // 文件备份功能
276+ if ( MainSettings . Default . RawSubtitleBuckup )
277+ {
278+ string buckupPath = Path . Combine ( OpenPath , "SubtitleFileBackup" ) ;
279+ try
280+ {
281+ if ( ! Directory . Exists ( buckupPath ) )
282+ Directory . CreateDirectory ( buckupPath ) ;
283+ File . Copy ( beforeFullPath , Path . Combine ( buckupPath , before ) , true ) ;
284+ }
285+ catch ( Exception e )
286+ {
287+ BeginInvoke ( ( MethodInvoker ) delegate
288+ {
289+ MessageBox . Show ( "原始字幕备份失败\n \n " + e . Message , "字幕备份失败" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
290+ } ) ;
291+ SubtitleChangedStatus [ before ] = "✖" ;
292+ continue ;
293+ }
294+ }
295+
296+ // 执行更名
297+ try
298+ {
299+ File . Move ( beforeFullPath , afterFullPath ) ;
300+ SubtitleChangedStatus [ before ] = "✔" ;
301+ }
302+ catch
303+ {
304+ // 更名失败
305+ SubtitleChangedStatus [ before ] = "✖" ;
306+ }
307+
308+ RefreshFileListBox ( ) ;
309+ }
310+
311+ SetCurtStatus ( "更名完毕" ) ;
312+ RefreshFileListBox ( ) ;
313+ OpenPathWatcher . EnableRaisingEvents = true ;
314+
315+ if ( MainSettings . Default . OpenFolderFinished )
316+ {
317+ Process . Start ( OpenPath ) ;
318+ }
165319 }
166320 }
167321}
0 commit comments