diff --git a/LanguageMaster.xml b/LanguageMaster.xml index 05e6389b5..fe27b25a9 100644 --- a/LanguageMaster.xml +++ b/LanguageMaster.xml @@ -2042,6 +2042,7 @@ can edit in same subtitle file (collaboration) Word lists ASS/SSA Style Network + File type associations Rules Show tool bar buttons New @@ -2506,6 +2507,8 @@ Continue? OCR Edit Shortcuts: Allow single letter/number in text box + Update file type associations + File type associations updated Download mpv lib diff --git a/build.bat b/build.bat index a7f35a1a8..48ad47d4e 100644 --- a/build.bat +++ b/build.bat @@ -172,7 +172,8 @@ IF NOT EXIST "temp_zip" MD "temp_zip" IF NOT EXIST "temp_zip\Languages" MD "temp_zip\Languages" IF NOT EXIST "temp_zip\Dictionaries" MD "temp_zip\Dictionaries" IF NOT EXIST "temp_zip\Ocr" MD "temp_zip\Ocr" -IF NOT EXIST "temp_zip\Tesseract302" MD "temp_zip\Tesseract302" +IF NOT EXIST "temp_zip\Tesseract302" MD "temp_zip\Tesseract302" +IF NOT EXIST "temp_zip\Icons" MD "temp_zip\Icons" ECHO. COPY /Y /V "..\..\..\..\LICENSE.txt" "temp_zip\" @@ -193,6 +194,7 @@ COPY /Y /V "Languages\*.xml" "temp_zip\Languages\" COPY /Y /V "..\..\..\..\Dictionaries\*.*" "temp_zip\Dictionaries\" COPY /Y /V "..\..\..\..\Ocr\*.*" "temp_zip\Ocr\" XCOPY /Y /V "..\..\..\..\Tesseract302\*.*" "temp_zip\Tesseract302\" /S +COPY /Y /V "..\..\..\..\Icons\*.ico" "temp_zip\Icons\" PUSHD "temp_zip" START "" /B /WAIT "%SEVENZIP%" a -tzip -mx=9 "SubtitleEdit-%VERSION%.zip" * >NUL diff --git a/build_beta.bat b/build_beta.bat index df9b64fa0..9fa1baff5 100644 --- a/build_beta.bat +++ b/build_beta.bat @@ -160,7 +160,8 @@ IF NOT EXIST "temp_zip" MD "temp_zip" IF NOT EXIST "temp_zip\Languages" MD "temp_zip\Languages" IF NOT EXIST "temp_zip\Dictionaries" MD "temp_zip\Dictionaries" IF NOT EXIST "temp_zip\Ocr" MD "temp_zip\Ocr" -IF NOT EXIST "temp_zip\Tesseract302" MD "temp_zip\Tesseract302" +IF NOT EXIST "temp_zip\Tesseract302" MD "temp_zip\Tesseract302" +IF NOT EXIST "temp_zip\Icons" MD "temp_zip\Icons" ECHO. COPY /Y /V "..\..\..\..\LICENSE.txt" "temp_zip\" @@ -181,6 +182,7 @@ COPY /Y /V "Languages\*.xml" "temp_zip\Languages\" COPY /Y /V "..\..\..\..\Dictionaries\*.*" "temp_zip\Dictionaries\" COPY /Y /V "..\..\..\..\Ocr\*.*" "temp_zip\Ocr\" XCOPY /Y /V "..\..\..\..\Tesseract302\*.*" "temp_zip\Tesseract302\" /S +COPY /Y /V "..\..\..\..\Icons\*.ico" "temp_zip\Icons\" PUSHD "temp_zip" START "" /B /WAIT "%SEVENZIP%" a -tzip -mx=9 "SubtitleEditBeta.zip" * >NUL diff --git a/installer/Subtitle_Edit_installer.iss b/installer/Subtitle_Edit_installer.iss index e4fa073c3..234fe5b76 100644 --- a/installer/Subtitle_Edit_installer.iss +++ b/installer/Subtitle_Edit_installer.iss @@ -435,55 +435,55 @@ Filename: {win}\Microsoft.NET\Framework64\v4.0.30319\ngen.exe; Parameters: "unin [Registry] -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: "" -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: "" -Root: HKA ; Subkey: "Software\Classes\.ass"; ValueData: "{#SetupSetting('AppName')}"; Flags: uninsdeletevalue; ValueType: string; ValueName: "" -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\SubtitleEdit.EXE,0"; +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: "" +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: "" +Root: HKCU ; Subkey: "Software\Classes\.ass"; ValueData: "{#SetupSetting('AppName')}"; Flags: uninsdeletevalue; ValueType: string; ValueName: "" +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\SubtitleEdit.EXE,0"; -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass') -Root: HKA ; Subkey: "Software\Classes\.ass"; ValueData: "{#SetupSetting('AppName')}.ass"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\ass.ico"; Check: DoSystemAssoc('ass') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass') +Root: HKCU ; Subkey: "Software\Classes\.ass"; ValueData: "{#SetupSetting('AppName')}.ass"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\ass.ico"; Check: DoSystemAssoc('ass') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp') -Root: HKA ; Subkey: "Software\Classes\.dfxp"; ValueData: "{#SetupSetting('AppName')}.dfxp"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\dfxp.ico"; Check: DoSystemAssoc('dfxp') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp') +Root: HKCU ; Subkey: "Software\Classes\.dfxp"; ValueData: "{#SetupSetting('AppName')}.dfxp"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\dfxp.ico"; Check: DoSystemAssoc('dfxp') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv') -Root: HKA ; Subkey: "Software\Classes\.sbv"; ValueData: "{#SetupSetting('AppName')}.sbv"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sbv.ico"; Check: DoSystemAssoc('sbv') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv') +Root: HKCU ; Subkey: "Software\Classes\.sbv"; ValueData: "{#SetupSetting('AppName')}.sbv"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sbv.ico"; Check: DoSystemAssoc('sbv') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt') -Root: HKA ; Subkey: "Software\Classes\.srt"; ValueData: "{#SetupSetting('AppName')}.srt"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\srt.ico"; Check: DoSystemAssoc('srt') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt') +Root: HKCU ; Subkey: "Software\Classes\.srt"; ValueData: "{#SetupSetting('AppName')}.srt"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\srt.ico"; Check: DoSystemAssoc('srt') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa') -Root: HKA ; Subkey: "Software\Classes\.ssa"; ValueData: "{#SetupSetting('AppName')}.ssa"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\ssa.ico"; Check: DoSystemAssoc('ssa') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa') +Root: HKCU ; Subkey: "Software\Classes\.ssa"; ValueData: "{#SetupSetting('AppName')}.ssa"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\ssa.ico"; Check: DoSystemAssoc('ssa') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl') -Root: HKA ; Subkey: "Software\Classes\.stl"; ValueData: "{#SetupSetting('AppName')}.stl"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\stl.ico"; Check: DoSystemAssoc('stl') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl') +Root: HKCU ; Subkey: "Software\Classes\.stl"; ValueData: "{#SetupSetting('AppName')}.stl"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\stl.ico"; Check: DoSystemAssoc('stl') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub') -Root: HKA ; Subkey: "Software\Classes\.sub"; ValueData: "{#SetupSetting('AppName')}.sub"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sub.ico"; Check: DoSystemAssoc('sub') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub') +Root: HKCU ; Subkey: "Software\Classes\.sub"; ValueData: "{#SetupSetting('AppName')}.sub"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sub.ico"; Check: DoSystemAssoc('sub') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup') -Root: HKA ; Subkey: "Software\Classes\.sup"; ValueData: "{#SetupSetting('AppName')}.sup"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sup.ico"; Check: DoSystemAssoc('sup') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup') +Root: HKCU ; Subkey: "Software\Classes\.sup"; ValueData: "{#SetupSetting('AppName')}.sup"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sup.ico"; Check: DoSystemAssoc('sup') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt') -Root: HKA ; Subkey: "Software\Classes\.vtt"; ValueData: "{#SetupSetting('AppName')}.vtt"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt') -Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\vtt.ico"; Check: DoSystemAssoc('vtt') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt') +Root: HKCU ; Subkey: "Software\Classes\.vtt"; ValueData: "{#SetupSetting('AppName')}.vtt"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt') +Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\vtt.ico"; Check: DoSystemAssoc('vtt') ; Add .ass (Advanced SubStation Alpha) to the SE-supported file types Root: HKLM; Subkey: "{#keyApps}\SubtitleEdit.exe\SupportedTypes"; ValueType: string; ValueName: ".ass"; ValueData: ""; Check: HklmKeyExists('{#keyApps}') @@ -556,11 +556,11 @@ var CurrentProgId, MyProgId, KeyName: String; begin KeyName := '{#keyCl}\.' + FileType; - if RegQueryStringValue(HKEY_LOCAL_MACHINE, KeyName, '', CurrentProgId) then + if RegQueryStringValue(HKEY_CURRENT_USER, KeyName, '', CurrentProgId) then begin MyProgId := 'SubtitleEdit.' + FileType; if CompareText(CurrentProgId, MyProgId) = 0 then - RegWriteStringValue(HKEY_LOCAL_MACHINE, KeyName, '', ''); + RegWriteStringValue(HKEY_CURRENT_USER, KeyName, '', ''); end; Result := IsTaskSelected('associate_common'); end; diff --git a/src/ui/Forms/Options/Settings.Designer.cs b/src/ui/Forms/Options/Settings.Designer.cs index 8af4026b4..5a29a0685 100644 --- a/src/ui/Forms/Options/Settings.Designer.cs +++ b/src/ui/Forms/Options/Settings.Designer.cs @@ -415,6 +415,12 @@ this.buttonReset = new System.Windows.Forms.Button(); this.toolTipContinuationPreview = new System.Windows.Forms.ToolTip(this.components); this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog(); + this.panelFileTypeAssociations = new System.Windows.Forms.Panel(); + this.labelUpdateFileTypeAssociationsStatus = new System.Windows.Forms.Label(); + this.buttonUpdateFileTypeAssociations = new System.Windows.Forms.Button(); + this.listViewFileTypeAssociations = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.imageListFileTypeAssociations = new System.Windows.Forms.ImageList(this.components); this.panelGeneral.SuspendLayout(); this.groupBoxMiscellaneous.SuspendLayout(); this.groupBoxGeneralRules.SuspendLayout(); @@ -487,6 +493,7 @@ this.groupBoxNetworkSession.SuspendLayout(); this.groupBoxProxySettings.SuspendLayout(); this.groupBoxProxyAuthentication.SuspendLayout(); + this.panelFileTypeAssociations.SuspendLayout(); this.SuspendLayout(); // // buttonOK @@ -529,7 +536,8 @@ "Wordlists", "Toolbar", "Font", - "Network"}); + "Network", + "File type associations"}); this.listBoxSection.Location = new System.Drawing.Point(10, 10); this.listBoxSection.Name = "listBoxSection"; this.listBoxSection.Size = new System.Drawing.Size(214, 516); @@ -5009,11 +5017,60 @@ this.toolTipContinuationPreview.InitialDelay = 500; this.toolTipContinuationPreview.ReshowDelay = 100; // + // panelFileTypeAssociations + // + this.panelFileTypeAssociations.Controls.Add(this.labelUpdateFileTypeAssociationsStatus); + this.panelFileTypeAssociations.Controls.Add(this.buttonUpdateFileTypeAssociations); + this.panelFileTypeAssociations.Controls.Add(this.listViewFileTypeAssociations); + this.panelFileTypeAssociations.Location = new System.Drawing.Point(230, 6); + this.panelFileTypeAssociations.Name = "panelFileTypeAssociations"; + this.panelFileTypeAssociations.Size = new System.Drawing.Size(852, 521); + this.panelFileTypeAssociations.TabIndex = 16; + // + // labelUpdateFileTypeAssociationsStatus + // + this.labelUpdateFileTypeAssociationsStatus.AutoSize = true; + this.labelUpdateFileTypeAssociationsStatus.Location = new System.Drawing.Point(16, 294); + this.labelUpdateFileTypeAssociationsStatus.Name = "labelUpdateFileTypeAssociationsStatus"; + this.labelUpdateFileTypeAssociationsStatus.Size = new System.Drawing.Size(35, 13); + this.labelUpdateFileTypeAssociationsStatus.TabIndex = 24; + this.labelUpdateFileTypeAssociationsStatus.Text = "label2"; + // + // buttonUpdateFileTypeAssociations + // + this.buttonUpdateFileTypeAssociations.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonUpdateFileTypeAssociations.Location = new System.Drawing.Point(16, 260); + this.buttonUpdateFileTypeAssociations.Name = "buttonUpdateFileTypeAssociations"; + this.buttonUpdateFileTypeAssociations.Size = new System.Drawing.Size(218, 23); + this.buttonUpdateFileTypeAssociations.TabIndex = 23; + this.buttonUpdateFileTypeAssociations.Text = "Update file type associations"; + this.buttonUpdateFileTypeAssociations.UseVisualStyleBackColor = true; + this.buttonUpdateFileTypeAssociations.Click += new System.EventHandler(this.buttonUpdateFileTypeAssociations_Click); + // + // listViewFileTypeAssociations + // + this.listViewFileTypeAssociations.CheckBoxes = true; + this.listViewFileTypeAssociations.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1}); + this.listViewFileTypeAssociations.HideSelection = false; + this.listViewFileTypeAssociations.Location = new System.Drawing.Point(0, 4); + this.listViewFileTypeAssociations.Name = "listViewFileTypeAssociations"; + this.listViewFileTypeAssociations.Size = new System.Drawing.Size(849, 241); + this.listViewFileTypeAssociations.TabIndex = 22; + this.listViewFileTypeAssociations.UseCompatibleStateImageBehavior = false; + // + // imageListFileTypeAssociations + // + this.imageListFileTypeAssociations.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit; + this.imageListFileTypeAssociations.ImageSize = new System.Drawing.Size(32, 32); + this.imageListFileTypeAssociations.TransparentColor = System.Drawing.Color.Transparent; + // // Settings // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1092, 574); + this.Controls.Add(this.panelFileTypeAssociations); this.Controls.Add(this.panelFont); this.Controls.Add(this.panelWaveform); this.Controls.Add(this.panelTools); @@ -5147,6 +5204,8 @@ this.groupBoxProxySettings.PerformLayout(); this.groupBoxProxyAuthentication.ResumeLayout(false); this.groupBoxProxyAuthentication.PerformLayout(); + this.panelFileTypeAssociations.ResumeLayout(false); + this.panelFileTypeAssociations.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -5540,5 +5599,11 @@ private System.Windows.Forms.Label labelBDOpensIn; private System.Windows.Forms.CheckBox checkBoxShortcutsAllowLetterOrNumberInTextBox; private System.Windows.Forms.CheckBox checkBoxWaveformAutoGen; + private System.Windows.Forms.Panel panelFileTypeAssociations; + private System.Windows.Forms.ListView listViewFileTypeAssociations; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ImageList imageListFileTypeAssociations; + private System.Windows.Forms.Button buttonUpdateFileTypeAssociations; + private System.Windows.Forms.Label labelUpdateFileTypeAssociationsStatus; } } \ No newline at end of file diff --git a/src/ui/Forms/Options/Settings.cs b/src/ui/Forms/Options/Settings.cs index aa42470b6..f38bc5ca9 100644 --- a/src/ui/Forms/Options/Settings.cs +++ b/src/ui/Forms/Options/Settings.cs @@ -33,6 +33,7 @@ namespace Nikse.SubtitleEdit.Forms.Options private const int ToolbarSection = 8; private const int AppearanceSection = 9; private const int NetworkSection = 10; + private const int FileTypeAssociationSection = 11; private string _listBoxSearchString = string.Empty; private DateTime _listBoxSearchStringLastUsed = DateTime.UtcNow; @@ -47,6 +48,8 @@ namespace Nikse.SubtitleEdit.Forms.Options private List _rulesProfiles; private List _pluginShortcuts; + private IEnumerable GetSubtitleFormats() => SubtitleFormat.AllSubtitleFormats.Where(format => !format.IsVobSubIndexFile).Select(format => format.FriendlyName); + private class ComboBoxLanguage { public CultureInfo CultureInfo { get; set; } @@ -115,6 +118,7 @@ namespace Nikse.SubtitleEdit.Forms.Options UiUtil.FixFonts(this); UiUtil.FixLargeFonts(this, buttonOK); Init(); + FillFileTypeAssociationsListView(); } public void Init() @@ -343,6 +347,7 @@ namespace Nikse.SubtitleEdit.Forms.Options listBoxSection.Items[ToolbarSection] = language.Toolbar; listBoxSection.Items[AppearanceSection] = language.Appearance; listBoxSection.Items[NetworkSection] = language.Network; + listBoxSection.Items[FileTypeAssociationSection] = language.FileTypeAssociations; Text = language.Title; panelGeneral.Text = language.General; @@ -1152,6 +1157,9 @@ namespace Nikse.SubtitleEdit.Forms.Options _oldListViewShowWpm = Configuration.Settings.Tools.ListViewShowColumnWordsPerMin; labelPlatform.Text = (IntPtr.Size * 8) + "-bit"; + + buttonUpdateFileTypeAssociations.Text = language.UpdateFileTypeAssociations; + labelUpdateFileTypeAssociationsStatus.Text = string.Empty; } private void SetDialogStyle(DialogType dialogStyle) @@ -2634,6 +2642,7 @@ namespace Nikse.SubtitleEdit.Forms.Options panelToolBar.Visible = false; panelFont.Visible = false; panelNetwork.Visible = false; + panelFileTypeAssociations.Visible = false; var section = panelGeneral; switch (listBoxSection.SelectedIndex) @@ -2668,6 +2677,9 @@ namespace Nikse.SubtitleEdit.Forms.Options case NetworkSection: section = panelNetwork; break; + case FileTypeAssociationSection: + section = panelFileTypeAssociations; + break; } section.Visible = true; @@ -3955,6 +3967,50 @@ namespace Nikse.SubtitleEdit.Forms.Options listBoxFavoriteSubtitleFormats.SetSelected(listBoxFavoriteSubtitleFormats.Items.Count - 1, true); } - private IEnumerable GetSubtitleFormats() => SubtitleFormat.AllSubtitleFormats.Where(format => !format.IsVobSubIndexFile).Select(format => format.FriendlyName); + private void FillFileTypeAssociationsListView() + { + var iconDir = Path.Combine(Configuration.BaseDirectory, "Icons"); + if (!Directory.Exists(iconDir)) + { + return; + } + + var iconFileNames = Directory.GetFiles(iconDir, "*.ico"); + listViewFileTypeAssociations.LargeImageList = imageListFileTypeAssociations; + foreach (var iconFileName in iconFileNames) + { + var friendlyName = "." + Path.GetFileNameWithoutExtension(iconFileName).ToUpperInvariant(); + var icon = new Icon(iconFileName); + imageListFileTypeAssociations.Images.Add(icon); + var item = new ListViewItem(friendlyName); + item.ImageIndex = imageListFileTypeAssociations.Images.Count - 1; + item.Checked = FileTypeAssociations.GetChecked("." + Path.GetFileNameWithoutExtension(iconFileName).ToLowerInvariant(), "Subtitle Edit"); + item.Tag = iconFileName; + listViewFileTypeAssociations.Items.Add(item); + } + listViewFileTypeAssociations.Refresh(); + } + + private void buttonUpdateFileTypeAssociations_Click(object sender, EventArgs e) + { + var exeFileName = Assembly.GetEntryAssembly().Location; + foreach (ListViewItem item in listViewFileTypeAssociations.Items) + { + var ext = item.Text.ToLowerInvariant(); + if (item.Checked) + { + var iconFileName = (string)item.Tag; + FileTypeAssociations.SetFileAssociationViaRegistry(ext, exeFileName, iconFileName, "Subtitle Edit"); + } + else + { + FileTypeAssociations.DeleteFileAssociationViaRegistry(ext, "Subtitle Edit"); + } + } + + labelUpdateFileTypeAssociationsStatus.Text = LanguageSettings.Current.Settings.FileTypeAssociationsUpdated; + FileTypeAssociations.Refresh(); + System.Threading.SynchronizationContext.Current.Post(TimeSpan.FromMilliseconds(3000), () => labelUpdateFileTypeAssociationsStatus.Text = string.Empty); + } } } diff --git a/src/ui/Forms/Options/Settings.resx b/src/ui/Forms/Options/Settings.resx index b551e3d64..33d62c9d6 100644 --- a/src/ui/Forms/Options/Settings.resx +++ b/src/ui/Forms/Options/Settings.resx @@ -118,21 +118,24 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 17, 17 + 232, 17 - 592, 17 + 807, 17 - 253, 17 + 468, 17 - 415, 17 + 630, 17 - 792, 17 + 1007, 17 - 17, 56 + 1210, 17 + + + 17, 17 \ No newline at end of file diff --git a/src/ui/Logic/FileTypeAssociations.cs b/src/ui/Logic/FileTypeAssociations.cs new file mode 100644 index 000000000..56d1592f6 --- /dev/null +++ b/src/ui/Logic/FileTypeAssociations.cs @@ -0,0 +1,80 @@ +using Microsoft.Win32; +using System; +using System.IO; + +namespace Nikse.SubtitleEdit.Logic +{ + internal static class FileTypeAssociations + { + [System.Runtime.InteropServices.DllImport("Shell32.dll")] + private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); + + internal static bool GetChecked(string ext, string appName) + { + using (RegistryKey key = Registry.CurrentUser.OpenSubKey($"Software\\Classes\\{appName}{ext}")) + { + if (key == null) + { + return false; + } + + var defaultIcon = key.OpenSubKey("DefaultIcon"); + if (defaultIcon == null) + { + return false; + } + + var iconFileNameObject = defaultIcon.GetValue(""); + if (iconFileNameObject == null || !(iconFileNameObject is string iconFileName) || !File.Exists(iconFileName)) + { + return false; + } + + var cmd = key.OpenSubKey("shell\\open\\command"); + if (cmd == null) + { + return false; + } + + var cmdObject = cmd.GetValue(""); + if (cmdObject != null && cmdObject is string cmdString) + { + var ix = cmdString.IndexOf("SubtitleEdit.exe"); + if (ix >= 0) + { + var exeFileName = cmdString.Substring(0, ix + "SubtitleEdit.exe".Length).Trim('"'); + return File.Exists(exeFileName); + } + } + } + + return false; + } + + internal static void SetFileAssociationViaRegistry(string ext, string exeFileName, string iconFileName, string appName) + { + Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{appName}{ext}", "", $"{ext.TrimStart('.')} subtitle file"); + Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{appName}{ext}\\DefaultIcon", "", iconFileName); + // Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{appName}{ext}", "FriendlyTypeName", "My Friendly Type Name"); + Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{appName}{ext}\\shell\\open\\command", "", $"\"{exeFileName.Trim('"')}\" \"%1\""); + Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{ext}", "", $"{appName}{ext}"); + } + + internal static void DeleteFileAssociationViaRegistry(string ext, string appName) + { + using (RegistryKey regkey = Registry.CurrentUser.OpenSubKey(@"Software\Classes\", true)) + { + if (regkey != null && regkey.OpenSubKey($"{appName}{ext}") != null) + { + regkey.DeleteSubKeyTree($"{appName}{ext}"); + } + } + } + + internal static void Refresh() + { + //this call notifies Windows that it needs to redo the file associations and icons + SHChangeNotify(0x08000000, 0x2000, IntPtr.Zero, IntPtr.Zero); + } + } +} diff --git a/src/ui/Logic/Language.cs b/src/ui/Logic/Language.cs index b82fb9581..480acd8f0 100644 --- a/src/ui/Logic/Language.cs +++ b/src/ui/Logic/Language.cs @@ -2369,6 +2369,7 @@ can edit in same subtitle file (collaboration)", WordLists = "Word lists", SsaStyle = "ASS/SSA Style", Network = "Network", + FileTypeAssociations = "File type associations", Rules = "Rules", NetworkSessionSettings = "Network session settings", NetworkSessionNewSound = "Play sound file when new message arrives", @@ -2833,6 +2834,8 @@ can edit in same subtitle file (collaboration)", BDOpensInOcr = "OCR", BDOpensInEdit = "Edit", ShortcutsAllowSingleLetterOrNumberInTextBox = "Shortcuts: Allow single letter/number in text box", + UpdateFileTypeAssociations = "Update file type associations", + FileTypeAssociationsUpdated = "File type associations updated", }; SettingsMpv = new LanguageStructure.SettingsMpv diff --git a/src/ui/Logic/LanguageDeserializer.cs b/src/ui/Logic/LanguageDeserializer.cs index fdee5edb5..87d041f8e 100644 --- a/src/ui/Logic/LanguageDeserializer.cs +++ b/src/ui/Logic/LanguageDeserializer.cs @@ -5503,6 +5503,9 @@ namespace Nikse.SubtitleEdit.Logic case "Settings/Network": language.Settings.Network = reader.Value; break; + case "Settings/FileTypeAssociations": + language.Settings.FileTypeAssociations = reader.Value; + break; case "Settings/Rules": language.Settings.Rules = reader.Value; break; @@ -6883,6 +6886,12 @@ namespace Nikse.SubtitleEdit.Logic case "Settings/ShortcutsAllowSingleLetterOrNumberInTextBox": language.Settings.ShortcutsAllowSingleLetterOrNumberInTextBox = reader.Value; break; + case "Settings/UpdateFileTypeAssociations": + language.Settings.UpdateFileTypeAssociations = reader.Value; + break; + case "Settings/FileTypeAssociationsUpdated": + language.Settings.FileTypeAssociationsUpdated = reader.Value; + break; case "SettingsMpv/DownloadMpv": language.SettingsMpv.DownloadMpv = reader.Value; break; diff --git a/src/ui/Logic/LanguageStructure.cs b/src/ui/Logic/LanguageStructure.cs index 0d6f8a641..0776789ff 100644 --- a/src/ui/Logic/LanguageStructure.cs +++ b/src/ui/Logic/LanguageStructure.cs @@ -2218,6 +2218,7 @@ public string WordLists { get; set; } public string SsaStyle { get; set; } public string Network { get; set; } + public string FileTypeAssociations { get; set; } public string Rules { get; set; } public string ShowToolBarButtons { get; set; } public string New { get; set; } @@ -2684,6 +2685,8 @@ public string BDOpensInOcr { get; set; } public string BDOpensInEdit { get; set; } public string ShortcutsAllowSingleLetterOrNumberInTextBox { get; set; } + public string UpdateFileTypeAssociations { get; set; } + public string FileTypeAssociationsUpdated { get; set; } } public class SettingsMpv diff --git a/src/ui/SubtitleEdit.csproj b/src/ui/SubtitleEdit.csproj index 51d6ea739..2ed7027f7 100644 --- a/src/ui/SubtitleEdit.csproj +++ b/src/ui/SubtitleEdit.csproj @@ -1237,6 +1237,7 @@ +