[gnome-subtitles: 4/6] #126 Undo/Redo in commands with text+translations



commit d7290bae59912d4d9647613f475c9ca35bf5dc82
Author: Pedro Castro <pedro gnomesubtitles org>
Date:   Tue May 14 08:42:43 2019 +0100

    #126 Undo/Redo in commands with text+translations
    
    Undo/Redo in commands with text and translations must consider if the
    translation was reloaded

 .../Core/Command/MergeSubtitlesCommand.cs          | 131 ++++++++++++++++-----
 .../Core/Command/SplitSubtitlesCommand.cs          |  13 +-
 2 files changed, 106 insertions(+), 38 deletions(-)
---
diff --git a/src/GnomeSubtitles/Core/Command/MergeSubtitlesCommand.cs 
b/src/GnomeSubtitles/Core/Command/MergeSubtitlesCommand.cs
index 1b0a884..8c0faea 100644
--- a/src/GnomeSubtitles/Core/Command/MergeSubtitlesCommand.cs
+++ b/src/GnomeSubtitles/Core/Command/MergeSubtitlesCommand.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of Gnome Subtitles.
- * Copyright (C) 2011 Pedro Castro
+ * Copyright (C) 2011-2019 Pedro Castro
  *
  * Gnome Subtitles is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,71 +17,142 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+using System;
 using GnomeSubtitles.Ui.View;
 using Gtk;
 using Mono.Unix;
 using SubLib.Core.Domain;
 using SubLib.Core.Timing;
-using System.Collections;
 
 namespace GnomeSubtitles.Core.Command {
 
 public class MergeSubtitlesCommand : MultipleSelectionCommand {
        private static string description = Catalog.GetString("Merging subtitles");
        private Subtitle[] subtitlesBefore = null;
-       private Subtitle subtitleAfter = null;
+       bool translationCleared = false; //Translation was cleared, so if we are undoing, we need to use the 
new translation text if present
 
        public MergeSubtitlesCommand () : base(description, false, SelectionIntended.Range, null) {
        }
 
        public override bool Execute () {
-               GnomeSubtitles.Ui.View.Subtitles subtitles = Base.Document.Subtitles;
-               int firstPathInt = Util.PathToInt(this.FirstPath);
-               int lastPathInt = Util.PathToInt(this.LastPath);
+               SetCommandTarget(Base.Document.IsTranslationLoaded ? CommandTarget.NormalAndTranslation : 
CommandTarget.Normal);
 
-               /* Store selected subtitles */
-               int subtitleCount = lastPathInt - firstPathInt + 1;
-               this.subtitlesBefore = new Subtitle[subtitleCount];
-               this.subtitlesBefore[0] = subtitles[firstPathInt].Clone(subtitles.Properties); //only the 
first needs to be cloned, the rest won't be changed
-               for (int index = 1, currentPath = firstPathInt + 1 ; index < subtitleCount ; index++, 
currentPath++) {
-                       this.subtitlesBefore[index] = subtitles[currentPath];
-               }
-
-               /* Merge subtitles */
-               MergeOperator mergeOperator = new MergeOperator(Base.Document.Subtitles);
-               if (!mergeOperator.Merge(firstPathInt, lastPathInt))
+               if (!Merge()) {
                        return false;
-               else {
-                       TreePath secondPath = Util.IntToPath(firstPathInt + 1);
-                       subtitles.RemoveRange(secondPath, this.LastPath);
-                       Base.Ui.View.RedrawPath(this.FirstPath);
-                       Base.Ui.View.Selection.Select(this.FirstPath, true, true);
-                       PostProcess();
-                       return true;
                }
-       }
 
+               PostProcess();
+               return true;
+       }
+       
        public override void Undo () {
-               if (this.subtitleAfter == null) {
-                       this.subtitleAfter = Base.Document.Subtitles[this.FirstPath];
+               /*
+                * If the command originally applied to translations and they have changed, we need to use 
the new translations because we didn't have them
+                * when this command was first executed. The same goes if the command didn't originally have 
translations but it now has.
+                */
+               bool hadTranslation = (this.Target == CommandTarget.NormalAndTranslation);
+               bool updateTranslation = Base.Document.IsTranslationLoaded && ((hadTranslation && 
translationCleared) || !hadTranslation);
+               
+               if (updateTranslation) {
+                       int firstSubtitleIndex = Util.PathToInt(this.FirstPath);
+                       Subtitle subtitle = Base.Document.Subtitles[firstSubtitleIndex];
+                       if (!subtitle.Translation.IsEmpty) {
+                               string[] translationLines = subtitle.Translation.GetLines();
+
+                               for (int i = 0; i < this.subtitlesBefore.Length; i++) {
+                                       Subtitle subtitleBefore = this.subtitlesBefore[i];
+                               
+                                       //If we don't have more translation lines, set it to empty
+                                       if (i >= translationLines.Length) {
+                                               subtitleBefore.Translation.Clear();
+                                               continue;
+                                       }
+
+                                       //If it's the last subtitle, check if we need to merge all remaining 
translations into it
+                                       if ((i == this.subtitlesBefore.Length - 1) && 
(this.subtitlesBefore.Length < translationLines.Length)) {
+                                               string lastLinesMerged = String.Join("\n", translationLines, 
i, translationLines.Length - this.subtitlesBefore.Length + 1);
+                                               subtitleBefore.Translation.Set(lastLinesMerged);
+                                               continue;
+                                       }
+
+                                       //Normal stuff, just set the translation line
+                                       subtitleBefore.Translation.Set(translationLines[i]);
+                               }
+                       }
+                       translationCleared = false;
                }
+
+               SetCommandTarget(Base.Document.IsTranslationLoaded ? CommandTarget.NormalAndTranslation : 
CommandTarget.Normal);
+               
                Base.Document.Subtitles.Remove(this.FirstPath);
                Base.Ui.View.Insert(this.subtitlesBefore, this.FirstPath, this.FirstPath);
                PostProcess();
        }
 
+       /*
+        * In Redo, we just run the Split command again, so we don't reuse old subtitles. Because of that, if 
a new translation
+        * has been loaded on the meanwhile, there's no problem, the current translation text will be used.
+        */
        public override void Redo () {
-               Base.Document.Subtitles.RemoveRange(this.FirstPath, this.LastPath);
-               Base.Ui.View.Insert(this.subtitleAfter, this.FirstPath);
+               SetCommandTarget(Base.Document.IsTranslationLoaded ? CommandTarget.NormalAndTranslation : 
CommandTarget.Normal);
+       
+               if (!Merge()) {
+                       return;
+               }
+
                PostProcess();
        }
+       
+       public override void ClearTarget (CommandTarget target) {
+               if (target == CommandTarget.Translation) {
+                       if (subtitlesBefore != null) {
+                               foreach (Subtitle subtitle in subtitlesBefore) {
+                                       if (subtitle.HasTranslation) {
+                                               subtitle.Translation.Clear();
+                                       }
+                               }
+                       }
+
+                       translationCleared = true;                      
+               }
+       }
+
 
        /* Protected members */
 
        protected void PostProcess () {
                Base.Ui.Video.SeekToSelection(true);
        }
+       
+       
+       /* Private members */
 
-}
+       private bool Merge () {
+               Ui.View.Subtitles subtitles = Base.Document.Subtitles;
+               int firstPathInt = Util.PathToInt(this.FirstPath);
+               int lastPathInt = Util.PathToInt(this.LastPath);
+
+               /* Store selected subtitles */
+               int subtitleCount = lastPathInt - firstPathInt + 1;
+               this.subtitlesBefore = new Subtitle[subtitleCount];
+               this.subtitlesBefore[0] = subtitles[firstPathInt].Clone(subtitles.Properties); //only the 
first needs to be cloned, the rest won't be changed
+               for (int index = 1, currentPath = firstPathInt + 1 ; index < subtitleCount ; index++, 
currentPath++) {
+                       this.subtitlesBefore[index] = subtitles[currentPath];
+               }
+
+               /* Merge subtitles */
+               MergeOperator mergeOperator = new MergeOperator(subtitles);
+               if (!mergeOperator.Merge(firstPathInt, lastPathInt)) {
+                       return false;
+               }
+
+               TreePath secondPath = Util.IntToPath(firstPathInt + 1);
+               subtitles.RemoveRange(secondPath, this.LastPath);
+               Base.Ui.View.RedrawPath(this.FirstPath);
+               Base.Ui.View.Selection.Select(this.FirstPath, true, true);
+               return true;
+       }
 
 }
+
+}
\ No newline at end of file
diff --git a/src/GnomeSubtitles/Core/Command/SplitSubtitlesCommand.cs 
b/src/GnomeSubtitles/Core/Command/SplitSubtitlesCommand.cs
index 0106815..d257a38 100644
--- a/src/GnomeSubtitles/Core/Command/SplitSubtitlesCommand.cs
+++ b/src/GnomeSubtitles/Core/Command/SplitSubtitlesCommand.cs
@@ -52,12 +52,11 @@ public class SplitSubtitlesCommand : MultipleSelectionCommand {
 
        public override void Undo () {
                /*
-                * If the command originally applied to translations and they have changed, we need to use 
the new translations because we didn't have them when this command was first executed.
-                * The same goes if the command didn't originally have translations but it now has.
+                * If the command originally applied to translations and they have changed, we need to use 
the new translations because we didn't have them
+                * when this command was first executed. The same goes if the command didn't originally have 
translations but it now has.
                 */
                bool hadTranslation = (this.Target == CommandTarget.NormalAndTranslation);
-               bool updateTranslation = Base.Document.IsTranslationLoaded
-                       && ((hadTranslation && translationCleared) || !hadTranslation);
+               bool updateTranslation = Base.Document.IsTranslationLoaded && ((hadTranslation && 
translationCleared) || !hadTranslation);
                
                if (updateTranslation) {
                        for (int i = 0; i < subtitlesBefore.Length; i++) {
@@ -88,8 +87,8 @@ public class SplitSubtitlesCommand : MultipleSelectionCommand {
 
 
        /*
-        * In Redo, we just run the Split command again, so we don't reuse existing subtitles. Because of 
that, if a new translation
-        * has been loaded there's no problem, its current text will be used.
+        * In Redo, we just run the Split command again, so we don't reuse old subtitles. Because of that, if 
a new translation
+        * has been loaded on the meanwhile, there's no problem, the current translation text will be used.
         */
        public override void Redo () {
                SetCommandTarget(Base.Document.IsTranslationLoaded ? CommandTarget.NormalAndTranslation : 
CommandTarget.Normal);
@@ -99,8 +98,6 @@ public class SplitSubtitlesCommand : MultipleSelectionCommand {
                }
 
                PostProcess();
-               
-               Split();
        }
        
        public override void ClearTarget (CommandTarget target) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]