From 79b2cce66cce22eb474aebda8c825438c4914e09 Mon Sep 17 00:00:00 2001 From: Nikolaj Olsson Date: Sun, 30 Dec 2018 09:38:35 +0100 Subject: [PATCH] Bookmarks are now saved in separate file (e.g. file.srt.bookmarks) Work on #3255 --- LanguageMaster.xml | 1 + libse/BookmarkPersistance.cs | 77 ++++++++++++++++++++++++++--------- libse/Language.cs | 1 + libse/LanguageDeserializer.cs | 3 ++ libse/LanguageStructure.cs | 1 + libse/Settings.cs | 5 +++ libse/Subtitle.cs | 2 - libse/Utilities.cs | 8 ++-- src/Forms/Main.cs | 23 ++++++----- src/Forms/Settings.cs | 1 + 10 files changed, 86 insertions(+), 36 deletions(-) diff --git a/LanguageMaster.xml b/LanguageMaster.xml index 0746c6ea6..ead32e455 100644 --- a/LanguageMaster.xml +++ b/LanguageMaster.xml @@ -2019,6 +2019,7 @@ can edit in same subtitle file (collaboration) Column, text down Focus waveform/spectrogram Go to next error + Auto balance selected lines (even 2+ lines) Start subtitle fullscreen beamer Move last word to next subtitle Fetch first word from next subtitle diff --git a/libse/BookmarkPersistance.cs b/libse/BookmarkPersistance.cs index 693f5703b..d788b8e53 100644 --- a/libse/BookmarkPersistance.cs +++ b/libse/BookmarkPersistance.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using System.Linq; +using System.IO; using System.Text; using Nikse.SubtitleEdit.Core.SubtitleFormats; @@ -8,22 +8,49 @@ namespace Nikse.SubtitleEdit.Core public class BookmarkPersistance { private readonly Subtitle _subtitle; + private readonly string _fileName; - public BookmarkPersistance(Subtitle subtitle) + public BookmarkPersistance(Subtitle subtitle, string fileName) { _subtitle = subtitle; + _fileName = fileName; } - public void SaveToFirstLine() + private string GetBookmarksFileName() { + return _fileName + ".bookmarks"; + } + + public bool Save() + { + if (_fileName == null) + return false; + + var fileName = GetBookmarksFileName(); var b = SerializeBookmarks(); if (b != null) { - var first = _subtitle.Paragraphs.FirstOrDefault(p => p.StartTime.TotalMilliseconds == 0 && p.EndTime.TotalMilliseconds == 0 && p.Text.Contains("\"bookmarks\"")); - if (first != null) - _subtitle.Paragraphs.Remove(first); - _subtitle.Paragraphs.Insert(0, new Paragraph(b, 0, 0)); + try + { + File.WriteAllText(fileName, b, Encoding.UTF8); + } + catch + { + return false; + } } + else if (File.Exists(fileName)) + { + try + { + File.Delete(fileName); + } + catch + { + return false; + } + } + return true; } private string SerializeBookmarks() @@ -53,27 +80,40 @@ namespace Nikse.SubtitleEdit.Core return null; } - public void LoadFromFirstLine() + public bool Load() { - var first = _subtitle.Paragraphs.FirstOrDefault(p => p.StartTime.TotalMilliseconds == 0 && p.EndTime.TotalMilliseconds == 0 && p.Text.Contains("\"bookmarks\"")); - if (first == null) - return; + if (_fileName == null) + return false; - var dic = DeserializeBookmarks(first.Text); - _subtitle.Paragraphs.Remove(first); - foreach (var kvp in dic) + var fileName = GetBookmarksFileName(); + if (File.Exists(fileName)) { - var p = _subtitle.GetParagraphOrDefault(kvp.Key); - if (p != null) + try { - p.Bookmark = kvp.Value; + var dic = DeserializeBookmarks(File.ReadAllText(fileName, Encoding.UTF8)); + foreach (var kvp in dic) + { + var p = _subtitle.GetParagraphOrDefault(kvp.Key); + if (p != null) + { + p.Bookmark = kvp.Value; + } + } + + } + catch + { + return false; } } + + return true; } private Dictionary DeserializeBookmarks(string s) { var dic = new Dictionary(); + s = s.Trim(); var bookmarks = Json.ReadObjectArray(s.Substring(s.IndexOf('[')).TrimEnd('}')); if (bookmarks == null || bookmarks.Count == 0) { @@ -84,8 +124,7 @@ namespace Nikse.SubtitleEdit.Core { var idx = Json.ReadTag(bm, "idx"); var txt = Json.ReadTag(bm, "txt"); - int number; - if (int.TryParse(idx, out number)) + if (int.TryParse(idx, out var number)) { dic.Add(number, txt); } diff --git a/libse/Language.cs b/libse/Language.cs index 03939b101..adcca6034 100644 --- a/libse/Language.cs +++ b/libse/Language.cs @@ -2309,6 +2309,7 @@ can edit in same subtitle file (collaboration)", ListViewColumnTextDown = "Column, text down", ListViewFocusWaveform = "Focus waveform/spectrogram", ListViewGoToNextError = "Go to next error", + ListViewAutoBalance2PlusLines = "Auto balance selected lines (even 2+ lines)", ShowBeamer = "Start subtitle fullscreen beamer", MainTextBoxMoveLastWordDown = "Move last word to next subtitle", MainTextBoxMoveFirstWordFromNextUp = "Fetch first word from next subtitle", diff --git a/libse/LanguageDeserializer.cs b/libse/LanguageDeserializer.cs index f4f5f2a3a..685fe5cee 100644 --- a/libse/LanguageDeserializer.cs +++ b/libse/LanguageDeserializer.cs @@ -5482,6 +5482,9 @@ namespace Nikse.SubtitleEdit.Core case "Settings/ListViewGoToNextError": language.Settings.ListViewGoToNextError = reader.Value; break; + case "Settings/ListViewAutoBalance2PlusLines": + language.Settings.ListViewAutoBalance2PlusLines = reader.Value; + break; case "Settings/ShowBeamer": language.Settings.ShowBeamer = reader.Value; break; diff --git a/libse/LanguageStructure.cs b/libse/LanguageStructure.cs index dd9ab9e0f..c9083eaf4 100644 --- a/libse/LanguageStructure.cs +++ b/libse/LanguageStructure.cs @@ -2184,6 +2184,7 @@ public string ListViewColumnTextDown { get; set; } public string ListViewFocusWaveform { get; set; } public string ListViewGoToNextError { get; set; } + public string ListViewAutoBalance2PlusLines { get; set; } public string ShowBeamer { get; set; } public string MainTextBoxMoveLastWordDown { get; set; } public string MainTextBoxMoveFirstWordFromNextUp { get; set; } diff --git a/libse/Settings.cs b/libse/Settings.cs index 376361e2b..418e6207a 100644 --- a/libse/Settings.cs +++ b/libse/Settings.cs @@ -1113,6 +1113,7 @@ $HorzAlign = Center public string MainListViewColumnTextDown { get; set; } public string MainListViewFocusWaveform { get; set; } public string MainListViewGoToNextError { get; set; } + public string MainListViewAutoBalance2PlusLines { get; set; } public string MainTextBoxItalic { get; set; } public string MainTextBoxSplitAtCursor { get; set; } public string MainTextBoxSplitAtCursorAndVideoPos { get; set; } @@ -3287,6 +3288,9 @@ $HorzAlign = Center subNode = node.SelectSingleNode("MainListViewGoToNextError"); if (subNode != null) settings.Shortcuts.MainListViewGoToNextError = subNode.InnerText; + subNode = node.SelectSingleNode("MainListViewAutoBalance2PlusLines"); + if (subNode != null) + settings.Shortcuts.MainListViewAutoBalance2PlusLines = subNode.InnerText; subNode = node.SelectSingleNode("MainEditReverseStartAndEndingForRTL"); if (subNode != null) settings.Shortcuts.MainEditReverseStartAndEndingForRTL = subNode.InnerText; @@ -4211,6 +4215,7 @@ $HorzAlign = Center textWriter.WriteElementString("MainListViewColumnTextDown", settings.Shortcuts.MainListViewColumnTextDown); textWriter.WriteElementString("MainListViewFocusWaveform", settings.Shortcuts.MainListViewFocusWaveform); textWriter.WriteElementString("MainListViewGoToNextError", settings.Shortcuts.MainListViewGoToNextError); + textWriter.WriteElementString("MainListViewAutoBalance2PlusLines", settings.Shortcuts.MainListViewAutoBalance2PlusLines); textWriter.WriteElementString("MainEditReverseStartAndEndingForRTL", settings.Shortcuts.MainEditReverseStartAndEndingForRTL); textWriter.WriteElementString("MainTextBoxItalic", settings.Shortcuts.MainTextBoxItalic); textWriter.WriteElementString("MainTextBoxSplitAtCursor", settings.Shortcuts.MainTextBoxSplitAtCursor); diff --git a/libse/Subtitle.cs b/libse/Subtitle.cs index d623e3e3e..07d44d0a6 100644 --- a/libse/Subtitle.cs +++ b/libse/Subtitle.cs @@ -612,8 +612,6 @@ namespace Nikse.SubtitleEdit.Core sb.Append((p.StartTime.TotalMilliseconds + Configuration.Settings.General.CurrentVideoOffsetInMs).GetHashCode()); sb.Append((p.EndTime.TotalMilliseconds + Configuration.Settings.General.CurrentVideoOffsetInMs).GetHashCode()); sb.Append(p.Text); - if (p.Bookmark != null) - sb.Append("*" + p.Bookmark); } return sb.ToString().TrimEnd(); } diff --git a/libse/Utilities.cs b/libse/Utilities.cs index de970123e..54fa16ec4 100644 --- a/libse/Utilities.cs +++ b/libse/Utilities.cs @@ -244,13 +244,13 @@ namespace Nikse.SubtitleEdit.Core public static string AutoBreakLineMoreThanTwoLines(string text, int maximumLineLength, string language) { - if (text == null || text.Length < 3) + if (text == null || text.Length < 3 || !text.Contains(" ")) return text; - string s = AutoBreakLine(text, 0, 0, language); + string s = AutoBreakLine(text, 0, Configuration.Settings.Tools.MergeLinesShorterThan, language); var arr = s.SplitToLines(); - if ((arr.Count < 2 && arr[0].Length <= maximumLineLength) || (arr[0].Length <= maximumLineLength && arr[1].Length <= maximumLineLength)) + if (arr.Count < 2 && arr[0].Length <= maximumLineLength || arr[0].Length <= maximumLineLength && arr[1].Length <= maximumLineLength) return s; s = RemoveLineBreaks(s); @@ -350,7 +350,7 @@ namespace Nikse.SubtitleEdit.Core public static string AutoBreakLine(string text, int maximumLength, int mergeLinesShorterThan, string language) { - if (text == null || text.Length < 3) + if (text == null || text.Length < 3 || !text.Contains(" ")) return text; // do not autobreak dialogs or music symbol diff --git a/src/Forms/Main.cs b/src/Forms/Main.cs index bdda6bf65..5e29b6c9a 100644 --- a/src/Forms/Main.cs +++ b/src/Forms/Main.cs @@ -235,6 +235,7 @@ namespace Nikse.SubtitleEdit.Forms private Keys _mainListViewAlignmentN9 = Keys.None; private Keys _mainListViewFocusWaveform = Keys.None; private Keys _mainListViewGoToNextError = Keys.None; + private Keys _mainListViewAutoBalance2PlusLines = Keys.None; private Keys _mainListViewCopyText = Keys.None; private Keys _mainEditReverseStartAndEndingForRTL = Keys.None; private Keys _waveformVerticalZoom = Keys.None; @@ -3032,7 +3033,7 @@ namespace Nikse.SubtitleEdit.Forms if (format != null) { - new BookmarkPersistance(_subtitle).LoadFromFirstLine(); + new BookmarkPersistance(_subtitle, fileName).Load(); if (Configuration.Settings.General.RemoveBlankLinesWhenOpening) { @@ -12367,10 +12368,11 @@ namespace Nikse.SubtitleEdit.Forms { _cancelWordSpellCheck = true; } - else if (inListView && (Keys.Shift | Keys.Control) == e.Modifiers && e.KeyCode == Keys.B) + else if (inListView && e.KeyData == _mainListViewAutoBalance2PlusLines) { AutoBalanceLinesAndAllow2PlusLines(); e.SuppressKeyPress = true; + e.Handled = true; } else if (audioVisualizer.Visible && e.KeyData == _waveformVerticalZoom) { @@ -12382,17 +12384,17 @@ namespace Nikse.SubtitleEdit.Forms audioVisualizer.VerticalZoomFactor /= 1.1; e.SuppressKeyPress = true; } - if (audioVisualizer.Visible && e.KeyData == _waveformZoomIn) + else if (audioVisualizer.Visible && e.KeyData == _waveformZoomIn) { audioVisualizer.ZoomIn(); e.SuppressKeyPress = true; } - if (audioVisualizer.Visible && e.KeyData == _waveformZoomOut) + else if (audioVisualizer.Visible && e.KeyData == _waveformZoomOut) { audioVisualizer.ZoomOut(); e.SuppressKeyPress = true; } - if (audioVisualizer.Visible && e.KeyData == _waveformSplit) + else if (audioVisualizer.Visible && e.KeyData == _waveformSplit) { if (mediaPlayer.IsPaused) { @@ -13625,6 +13627,7 @@ namespace Nikse.SubtitleEdit.Forms ShowHideBookmark(p); } SubtitleListview1.StateImageList = _subtitle != null && _subtitle.Paragraphs.Any(p => p.Bookmark != null) ? imageListBookmarks : null; + new BookmarkPersistance(_subtitle, _fileName).Save(); } private void ClearBookmarks() @@ -13642,6 +13645,7 @@ namespace Nikse.SubtitleEdit.Forms var p = _subtitle.GetParagraphOrDefault(_subtitleListViewIndex); if (p != null) ShowHideBookmark(p); + new BookmarkPersistance(_subtitle, _fileName).Save(); } private void MoveWordUpDownInCurrent(bool down) @@ -17750,6 +17754,7 @@ namespace Nikse.SubtitleEdit.Forms _mainListViewAlignmentN9 = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainListViewAlignmentN9); _mainListViewFocusWaveform = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainListViewFocusWaveform); _mainListViewGoToNextError = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainListViewGoToNextError); + _mainListViewAutoBalance2PlusLines = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainListViewAutoBalance2PlusLines); _mainEditReverseStartAndEndingForRTL = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainEditReverseStartAndEndingForRTL); _mainListViewCopyText = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainListViewCopyText); copyOriginalTextToCurrentToolStripMenuItem.ShortcutKeys = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainListViewCopyTextFromOriginalToCurrent); @@ -22592,7 +22597,6 @@ namespace Nikse.SubtitleEdit.Forms { sub.AddTimeToAllParagraphs(TimeSpan.FromMilliseconds(Configuration.Settings.General.CurrentVideoOffsetInMs)); } - new BookmarkPersistance(sub).SaveToFirstLine(); return sub; } @@ -23573,11 +23577,6 @@ namespace Nikse.SubtitleEdit.Forms ListViewToggleTag("box"); } - private void pictureBoxBookmark_Click(object sender, EventArgs e) - { - - } - private void ShowHideBookmark(Paragraph p) { if (!string.IsNullOrWhiteSpace(p.Bookmark)) @@ -23659,6 +23658,7 @@ namespace Nikse.SubtitleEdit.Forms SubtitleListview1.ShowState(_subtitleListViewIndex, p1); ShowHideBookmark(p1); SubtitleListview1.StateImageList = _subtitle != null && _subtitle.Paragraphs.Any(p => p.Bookmark != null) ? imageListBookmarks : null; + new BookmarkPersistance(_subtitle, _fileName).Save(); } } } @@ -23676,6 +23676,7 @@ namespace Nikse.SubtitleEdit.Forms SubtitleListview1.ShowState(_subtitleListViewIndex, p2); ShowHideBookmark(p2); SubtitleListview1.StateImageList = _subtitle != null && _subtitle.Paragraphs.Any(p => p.Bookmark != null) ? imageListBookmarks : null; + new BookmarkPersistance(_subtitle, _fileName).Save(); } }; _bookmarkContextMenu.MenuItems.Add(menuItem); diff --git a/src/Forms/Settings.cs b/src/Forms/Settings.cs index 799de46b2..23de00c53 100644 --- a/src/Forms/Settings.cs +++ b/src/Forms/Settings.cs @@ -938,6 +938,7 @@ namespace Nikse.SubtitleEdit.Forms AddNode(listViewNode, language.ListViewColumnTextDown, nameof(Configuration.Settings.Shortcuts.MainListViewColumnTextDown), true); AddNode(listViewNode, language.ListViewFocusWaveform, nameof(Configuration.Settings.Shortcuts.MainListViewFocusWaveform)); AddNode(listViewNode, language.ListViewGoToNextError, nameof(Configuration.Settings.Shortcuts.MainListViewGoToNextError)); + AddNode(listViewNode, language.ListViewAutoBalance2PlusLines, nameof(Configuration.Settings.Shortcuts.MainListViewAutoBalance2PlusLines)); if (listViewNode.Nodes.Count > 0) _shortcuts.Nodes.Add(listViewNode);