[gnome-subtitles] Fix bug#565360 - Periodically backup subtitle files, based on a patch from Arx Cruz



commit f196d7c2db7ffdc3bbed1780a2708eb1ffd0998d
Author: Pedro Castro <mail pedrocastro org>
Date:   Sun Jun 27 12:42:52 2010 +0100

    Fix bug#565360 - Periodically backup subtitle files, based on a patch from Arx Cruz

 data/gnome-subtitles.schemas                   |   22 ++++
 gnome-subtitles.mdp                            |    1 +
 src/Glade/MainWindow.glade                     |   18 ++--
 src/Glade/PreferencesDialog.glade              |   80 +++++++++++-
 src/GnomeSubtitles/Core/Backup.cs              |  160 ++++++++++++++++++++++++
 src/GnomeSubtitles/Core/Base.cs                |    8 +-
 src/GnomeSubtitles/Core/Config.cs              |   20 +++-
 src/GnomeSubtitles/Dialog/PreferencesDialog.cs |   28 ++++
 src/SubLib/Core/Domain/FileProperties.cs       |   14 ++-
 src/SubLib/Core/Domain/Frames.cs               |   24 +++-
 src/SubLib/Core/Domain/Headers.cs              |   14 ++-
 src/SubLib/Core/Domain/Style.cs                |   14 ++-
 src/SubLib/Core/Domain/Subtitle.cs             |   39 ++++++-
 src/SubLib/Core/Domain/SubtitleCollection.cs   |   36 ++++--
 src/SubLib/Core/Domain/SubtitleProperties.cs   |   14 ++-
 src/SubLib/Core/Domain/SubtitleText.cs         |   19 +++-
 src/SubLib/Core/Domain/Subtitles.cs            |   18 +++-
 src/SubLib/Core/Domain/Times.cs                |   19 +++-
 18 files changed, 503 insertions(+), 45 deletions(-)
---
diff --git a/data/gnome-subtitles.schemas b/data/gnome-subtitles.schemas
index b98eff0..439dfa1 100644
--- a/data/gnome-subtitles.schemas
+++ b/data/gnome-subtitles.schemas
@@ -189,5 +189,27 @@
 				<long>Newline type to use when saving files.</long>
 			</locale>
 		</schema>
+		<schema>
+			<key>/schemas/apps/gnome-subtitles/preferences/backup/auto_backup</key>
+			<applyto>/apps/gnome-subtitles/preferences/backup/auto_backup</applyto>
+			<owner>gnome-subtitles</owner>
+			<type>bool</type>
+			<default>TRUE</default>
+			<locale name="C">
+				<short>Auto backup</short>
+				<long>Whether to automatically backup files. A copy of the file will be periodically saved with a ~ suffix.</long>
+			</locale>
+		</schema>
+		<schema>
+			<key>/schemas/apps/gnome-subtitles/preferences/backup/backup_time</key>
+			<applyto>/apps/gnome-subtitles/preferences/backup/backup_time</applyto>
+			<owner>gnome-subtitles</owner>
+			<type>int</type>
+			<default>120</default>
+			<locale name="C">
+				<short>Backup time</short>
+				<long>Time interval, in seconds, to automatically backup files. A minimum of 30 seconds is recommended.</long>
+			</locale>
+		</schema>
 	</schemalist>
 </gconfschemafile>
diff --git a/gnome-subtitles.mdp b/gnome-subtitles.mdp
index 3daad3f..b97af37 100644
--- a/gnome-subtitles.mdp
+++ b/gnome-subtitles.mdp
@@ -248,6 +248,7 @@
     <File subtype="Code" buildaction="Compile" name="src/GnomeSubtitles/Ui/Component/SubtitleFormatComboBox.cs" />
     <File subtype="Code" buildaction="Compile" name="src/GnomeSubtitles/Ui/Component/NewlineTypeComboBox.cs" />
     <File subtype="Code" buildaction="Compile" name="src/GnomeSubtitles/Ui/VideoPreview/SubtitleTracker.cs" />
+    <File subtype="Code" buildaction="Compile" name="src/GnomeSubtitles/Core/Backup.cs" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" />
diff --git a/src/Glade/MainWindow.glade b/src/Glade/MainWindow.glade
index 741e09e..c1bfe53 100644
--- a/src/Glade/MainWindow.glade
+++ b/src/Glade/MainWindow.glade
@@ -248,8 +248,8 @@
                         <property name="use_underline">True</property>
                         <property name="use_stock">True</property>
                         <signal name="activate" handler="OnEditRedo"/>
-                        <accelerator key="Y" signal="activate" modifiers="GDK_CONTROL_MASK"/>
                         <accelerator key="Z" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
+                        <accelerator key="Y" signal="activate" modifiers="GDK_CONTROL_MASK"/>
                       </widget>
                     </child>
                     <child>
@@ -532,8 +532,8 @@
                         <property name="label" translatable="yes">Find Ne_xt</property>
                         <property name="use_underline">True</property>
                         <signal name="activate" handler="OnSearchFindNext"/>
-                        <accelerator key="F3" signal="activate"/>
                         <accelerator key="g" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+                        <accelerator key="F3" signal="activate"/>
                       </widget>
                     </child>
                     <child>
@@ -543,8 +543,8 @@
                         <property name="label" translatable="yes">Find Pre_vious</property>
                         <property name="use_underline">True</property>
                         <signal name="activate" handler="OnSearchFindPrevious"/>
-                        <accelerator key="F3" signal="activate" modifiers="GDK_SHIFT_MASK"/>
                         <accelerator key="g" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
+                        <accelerator key="F3" signal="activate" modifiers="GDK_SHIFT_MASK"/>
                       </widget>
                     </child>
                     <child>
@@ -803,8 +803,8 @@
                         <property name="use_underline">True</property>
                         <property name="use_stock">False</property>
                         <signal name="activate" handler="OnVideoPlayPause"/>
-                        <accelerator key="F5" signal="activate"/>
                         <accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+                        <accelerator key="F5" signal="activate"/>
                         <child internal-child="image">
                           <widget class="GtkImage" id="videoPlayPauseImage">
                             <property name="visible">True</property>
@@ -822,8 +822,8 @@
                         <property name="use_underline">True</property>
                         <property name="use_stock">False</property>
                         <signal name="activate" handler="OnVideoRewind"/>
-                        <accelerator key="F6" signal="activate"/>
                         <accelerator key="k" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+                        <accelerator key="F6" signal="activate"/>
                         <child internal-child="image">
                           <widget class="GtkImage" id="videoRewindImage">
                             <property name="visible">True</property>
@@ -841,8 +841,8 @@
                         <property name="use_underline">True</property>
                         <property name="use_stock">False</property>
                         <signal name="activate" handler="OnVideoForward"/>
-                        <accelerator key="F7" signal="activate"/>
                         <accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+                        <accelerator key="F7" signal="activate"/>
                         <child internal-child="image">
                           <widget class="GtkImage" id="videoForwardImage">
                             <property name="visible">True</property>
@@ -882,8 +882,8 @@
                         <property name="label" translatable="yes">Seek _to Selection</property>
                         <property name="use_underline">True</property>
                         <signal name="activate" handler="OnVideoSeekToSelection"/>
-                        <accelerator key="F10" signal="activate"/>
                         <accelerator key="r" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
+                        <accelerator key="F4" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
                       </widget>
                     </child>
                     <child>
@@ -893,7 +893,7 @@
                         <property name="label" translatable="yes">Select Nearest Subtitle</property>
                         <property name="use_underline">True</property>
                         <signal name="activate" handler="OnVideoSelectNearestSubtitle"/>
-                        <accelerator key="F9" signal="activate"/>
+                        <accelerator key="F4" signal="activate" modifiers="GDK_CONTROL_MASK"/>
                         <accelerator key="r" signal="activate" modifiers="GDK_CONTROL_MASK"/>
                       </widget>
                     </child>
@@ -903,7 +903,7 @@
                         <property name="label" translatable="yes">Auto Select Subtitles</property>
                         <property name="use_underline">True</property>
                         <signal name="toggled" handler="OnVideoAutoSelectSubtitles"/>
-                        <accelerator key="F11" signal="activate"/>
+                        <accelerator key="F3" signal="activate" modifiers="GDK_CONTROL_MASK"/>
                         <accelerator key="j" signal="activate" modifiers="GDK_CONTROL_MASK"/>
                       </widget>
                     </child>
diff --git a/src/Glade/PreferencesDialog.glade b/src/Glade/PreferencesDialog.glade
index d908f54..fa005fc 100644
--- a/src/Glade/PreferencesDialog.glade
+++ b/src/Glade/PreferencesDialog.glade
@@ -12,12 +12,10 @@
       <widget class="GtkVBox" id="dialogVBox">
         <property name="visible">True</property>
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
-        <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child>
           <widget class="GtkVBox" id="vbox1">
             <property name="visible">True</property>
-            <property name="orientation">vertical</property>
             <property name="spacing">10</property>
             <child>
               <widget class="GtkFrame" id="frame3">
@@ -31,7 +29,6 @@
                     <child>
                       <widget class="GtkVBox" id="vbox2">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
                         <property name="spacing">5</property>
                         <child>
                           <widget class="GtkCheckButton" id="translationSaveAllCheckButton">
@@ -79,7 +76,6 @@
                     <child>
                       <widget class="GtkVBox" id="vbox4">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
                         <property name="spacing">5</property>
                         <child>
                           <widget class="GtkTable" id="table2">
@@ -275,6 +271,82 @@
                 <property name="position">2</property>
               </packing>
             </child>
+            <child>
+              <widget class="GtkFrame" id="frame4">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment4">
+                    <property name="visible">True</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <widget class="GtkHBox" id="hbox1">
+                        <property name="visible">True</property>
+                        <property name="spacing">3</property>
+                        <child>
+                          <widget class="GtkCheckButton" id="autoBackupCheckButton">
+                            <property name="label" translatable="yes">Create a _backup copy of files every</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_underline">True</property>
+                            <property name="draw_indicator">True</property>
+                            <signal name="toggled" handler="OnAutoBackupToggled"/>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkSpinButton" id="autoBackupTimeSpinButton">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="max_length">2</property>
+                            <property name="invisible_char">&#x25CF;</property>
+                            <property name="width_chars">2</property>
+                            <property name="adjustment">1 1 100 1 2 0</property>
+                            <property name="numeric">True</property>
+                            <signal name="value_changed" handler="OnAutoBackupTimeSpinButonValueChanged"/>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label9">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">minutes</property>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label8">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Backup&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">3</property>
+              </packing>
+            </child>
           </widget>
           <packing>
             <property name="expand">False</property>
diff --git a/src/GnomeSubtitles/Core/Backup.cs b/src/GnomeSubtitles/Core/Backup.cs
new file mode 100644
index 0000000..b374bae
--- /dev/null
+++ b/src/GnomeSubtitles/Core/Backup.cs
@@ -0,0 +1,160 @@
+/*
+ * This file is part of Gnome Subtitles.
+ * Copyright (C) 2010 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Gnome Subtitles is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+using System;
+using System.IO;
+using System.Threading;
+using GnomeSubtitles.Ui;
+using Gtk;
+using SubLib.Core;
+using SubLib.Core.Domain;
+
+namespace GnomeSubtitles.Core {
+
+public class Backup {
+	private uint backupTimeoutId = 0; //Active timeout ID, used to remove timeout if needed
+	
+	public Backup () {
+		Base.InitFinished += OnBaseInitFinished;
+	}
+	
+
+	/* Public methods */
+	
+	/* ReCheck forces restart if we're enabling backup and it's already running */
+	public void ReCheck () {
+		if (IsBackupRunning()) {
+			Disable();
+		}
+	
+		if (Base.Config.PrefsBackupAutoBackup) {
+			Enable();
+		}
+	}
+	
+	
+	/* Private members */
+	
+	private bool IsBackupRunning () {
+		return backupTimeoutId != 0;
+	}
+	
+	private void Enable() {
+		if (backupTimeoutId == 0)
+			backupTimeoutId = GLib.Timeout.Add((uint)Base.Config.PrefsBackupBackupTime * 1000, DoBackup); //milliseconds
+	}
+	
+	private void Disable() {
+		if (backupTimeoutId != 0) {
+			GLib.Source.Remove(backupTimeoutId);
+			backupTimeoutId = 0;
+		}
+	}
+	
+	private bool DoBackup() {
+		if (!Base.IsDocumentLoaded)
+			return true;
+		
+		BackupThreadArgs backupThreadArgs = new BackupThreadArgs();
+		if (Base.Document.CanTextBeSaved) {
+			backupThreadArgs.TextFilePropertiesClone = Base.Document.TextFile.Clone() as SubLib.Core.Domain.FileProperties;
+		}
+		
+		if (Base.Document.CanTranslationBeSaved) {
+			backupThreadArgs.TranslationFilePropertiesClone = Base.Document.TranslationFile.Clone() as SubLib.Core.Domain.FileProperties;
+		}
+
+		if ((backupThreadArgs.TextFilePropertiesClone != null) || (backupThreadArgs.TranslationFilePropertiesClone != null)) {
+			backupThreadArgs.SubtitlesClone = Base.Document.Subtitles.Clone() as SubLib.Core.Domain.Subtitles;
+			Thread backupThread = new Thread(SaveSubtitleFiles);
+			backupThread.Start(backupThreadArgs);
+		}
+
+		return true;
+	}
+	
+	private void SaveSubtitleFiles (object backupThreadArgs) {
+		try {
+			BackupThreadArgs args = backupThreadArgs as BackupThreadArgs;
+			
+			/* Save subtitle file */
+			if ((args.TextFilePropertiesClone != null) && (args.TextFilePropertiesClone.SubtitleType != SubtitleType.Unknown) && (args.TextFilePropertiesClone.IsPathRooted)) {
+				args.TextFilePropertiesClone.Path += "~";
+				SaveFile(args.SubtitlesClone, args.TextFilePropertiesClone, SubtitleTextType.Text);
+			}
+			
+			/* Save translation file */
+			if ((args.TranslationFilePropertiesClone != null) && (args.TranslationFilePropertiesClone.SubtitleType != SubtitleType.Unknown) && (args.TranslationFilePropertiesClone.IsPathRooted)) {
+				args.TranslationFilePropertiesClone.Path += "~";
+				SaveFile(args.SubtitlesClone, args.TranslationFilePropertiesClone, SubtitleTextType.Translation);
+			}
+		}
+		catch (Exception e) {
+			Console.Error.WriteLine("Caught exception creating backup files: " + e);
+		}
+	}
+	
+	private bool SaveFile (SubLib.Core.Domain.Subtitles subtitles, FileProperties properties, SubtitleTextType textType) {
+		try {
+			SubtitleSaver saver = new SubtitleSaver();
+			saver.Save(subtitles, properties, textType);
+			return true;
+		}
+		catch (Exception e) {
+			Console.Error.WriteLine("Caught exception saving backup file: " + e);
+			return false;
+		}
+	}
+	
+	/* Event members */
+	
+	private void OnBaseInitFinished () {
+		if (Base.Config.PrefsBackupAutoBackup) {
+			Enable();
+		}
+    }
+    
+    
+    /* Inner classes */
+
+    private class BackupThreadArgs {
+    	private SubLib.Core.Domain.Subtitles subtitlesClone;
+    	private SubLib.Core.Domain.FileProperties textFilePropertiesClone;
+    	private SubLib.Core.Domain.FileProperties translationFilePropertiesClone;
+
+		/* Properties */
+
+    	public SubLib.Core.Domain.Subtitles SubtitlesClone {
+    		get { return subtitlesClone; }
+    		set { this.subtitlesClone = value; }
+    	}
+    	
+    	public SubLib.Core.Domain.FileProperties TextFilePropertiesClone {
+    		get { return textFilePropertiesClone; }
+    		set { this.textFilePropertiesClone = value; }
+    	}
+    	
+    	public SubLib.Core.Domain.FileProperties TranslationFilePropertiesClone {
+    		get { return translationFilePropertiesClone; }
+    		set { this.translationFilePropertiesClone = value; }
+    	}
+    }
+
+}
+}
diff --git a/src/GnomeSubtitles/Core/Base.cs b/src/GnomeSubtitles/Core/Base.cs
index 0185e38..8294108 100644
--- a/src/GnomeSubtitles/Core/Base.cs
+++ b/src/GnomeSubtitles/Core/Base.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of Gnome Subtitles.
- * Copyright (C) 2006-2009 Pedro Castro
+ * Copyright (C) 2006-2010 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
@@ -48,6 +48,7 @@ public class Base {
 	private static Config config = null;
 	private static Dialogs dialogs = null;
 	private static SpellLanguages spellLanguages = null;
+	private static Backup backup = null;
 	
 	private static Document document = null;
 	private static Uri videoUri = null;
@@ -102,6 +103,10 @@ public class Base {
 		get { return spellLanguages; }
 	}
 	
+	public static Backup Backup {
+		get { return backup; }	
+	}
+	
 	public static Document Document {
 		get { return document; }
 	}
@@ -270,6 +275,7 @@ public class Base {
 		config = new Config();
 		dialogs = new Dialogs();
 		spellLanguages = new SpellLanguages();
+		backup = new Backup();
 
 		/* Initialize the GUI */
 		ui = new MainUi(handlers, out glade);
diff --git a/src/GnomeSubtitles/Core/Config.cs b/src/GnomeSubtitles/Core/Config.cs
index 27560f3..9a59e90 100644
--- a/src/GnomeSubtitles/Core/Config.cs
+++ b/src/GnomeSubtitles/Core/Config.cs
@@ -45,6 +45,7 @@ public class Config {
 	private const string keyPrefsWindow = keyPrefs + "window/";
 	private const string keyPrefsDefaults = keyPrefs + "defaults/";
 	private const string keyPrefsTranslation = keyPrefs + "translation/";
+	private const string keyPrefsBackup = keyPrefs + "backup/";
 
 	/* Constant key strings */
 	private const string keyPrefsEncodingsShownInMenu = keyPrefsEncodings + "shown_in_menu";
@@ -64,7 +65,9 @@ public class Config {
 	private const string keyPrefsDefaultsFileSaveFormat = keyPrefsDefaults + "file_save_format";
 	private const string keyPrefsDefaultsFileSaveNewlineOption = keyPrefsDefaults + "file_save_newline_option";
 	private const string keyPrefsDefaultsFileSaveNewline = keyPrefsDefaults + "file_save_newline";
-	
+	private const string keyPrefsBackupAutoBackup = keyPrefsBackup + "auto_backup";
+	private const string keyPrefsBackupBackupTime = keyPrefsBackup + "backup_time";
+
 
 	public Config () {
 		client = new Client();
@@ -183,6 +186,18 @@ public class Config {
 		get { return GetBool(keyPrefsTranslationSaveAll, true); }
 		set { Set(keyPrefsTranslationSaveAll, value); }
 	}
+	
+	//Even though the default in gconf schema is true, if gconf is not working we're using false
+	public bool PrefsBackupAutoBackup {
+		get { return GetBool(keyPrefsBackupAutoBackup, false); }
+		set { Set(keyPrefsBackupAutoBackup, value); }
+	}
+ 
+	/* Backup time in seconds */
+	public int PrefsBackupBackupTime {
+		get { return GetInt(keyPrefsBackupBackupTime, 120, 30, true, 0, false); }
+		set { Set(keyPrefsBackupBackupTime, value); }
+	}
 
 	
 	/* Private members */
@@ -247,8 +262,7 @@ public class Config {
 		}
 	}
 
-	/* Gets an enum value from a field which can hold a value not included in the enum (basically assumes an exception
-		can occur). */
+	/* Gets an enum value from a field which can hold a value not included in the enum (basically assumes an exception can occur). */
 	private Enum GetEnumValueFromSuperset (string key, Enum defaultValue) {
 		try {
 			string stringValue = (string)client.Get(key);
diff --git a/src/GnomeSubtitles/Dialog/PreferencesDialog.cs b/src/GnomeSubtitles/Dialog/PreferencesDialog.cs
index 4a8cc7b..7eaf421 100644
--- a/src/GnomeSubtitles/Dialog/PreferencesDialog.cs
+++ b/src/GnomeSubtitles/Dialog/PreferencesDialog.cs
@@ -42,11 +42,13 @@ public class PreferencesDialog : GladeDialog {
 	/* Widgets */
 	[WidgetAttribute] private CheckButton translationSaveAllCheckButton = null;
 	[WidgetAttribute] private CheckButton videoAutoChooseFileCheckButton = null;
+	[WidgetAttribute] private CheckButton autoBackupCheckButton = null;
 	[WidgetAttribute] private ComboBox fileOpenEncodingComboBox = null;
 	[WidgetAttribute] private ComboBox fileOpenFallbackEncodingComboBox = null;
 	[WidgetAttribute] private ComboBox fileSaveEncodingComboBox = null;
 	[WidgetAttribute] private ComboBox fileSaveFormatComboBox = null;
 	[WidgetAttribute] private ComboBox fileSaveNewlineComboBox = null;
+	[WidgetAttribute] private SpinButton autoBackupTimeSpinButton = null;
 
 
 	public PreferencesDialog () : base(gladeFilename, false) {
@@ -60,6 +62,7 @@ public class PreferencesDialog : GladeDialog {
 		/* Translation Save All */
 		translationSaveAllCheckButton.Active = Base.Config.PrefsTranslationSaveAll;
 
+		/* Defaults */
 		SetDefaultsFileOpenEncoding();
 		SetDefaultsFileOpenFallbackEncoding();
 		SetDefaultsFileSaveEncoding();
@@ -68,6 +71,9 @@ public class PreferencesDialog : GladeDialog {
 
 		/* Video Auto choose file */
 		videoAutoChooseFileCheckButton.Active = Base.Config.PrefsVideoAutoChooseFile;
+		
+		/* Auto Backup */
+		SetAutoBackup();
 	}
 
 	private void SetDefaultsFileOpenEncoding () {
@@ -149,6 +155,12 @@ public class PreferencesDialog : GladeDialog {
 		}
 		fileSaveNewline.SelectionChanged += OnDefaultsFileSaveNewlineChanged;
 	}
+	
+	private void SetAutoBackup () {
+		bool autoBackupEnabled = Base.Config.PrefsBackupAutoBackup;
+		autoBackupCheckButton.Active = autoBackupEnabled;
+		autoBackupTimeSpinButton.Sensitive = autoBackupEnabled;
+	}
 
 	private void ResetDialogToDefaults () {
 		translationSaveAllCheckButton.Active = true;
@@ -160,6 +172,8 @@ public class PreferencesDialog : GladeDialog {
 		fileSaveEncoding.ActiveSelection = 0; //Keep Existing
 		fileSaveFormat.ActiveSelection = 0; //Keep Existing
 		fileSaveNewline.ChosenNewlineType = NewlineType.Windows;
+		
+		autoBackupCheckButton.Active = true;
 	}
 
 	
@@ -273,6 +287,20 @@ public class PreferencesDialog : GladeDialog {
 	private void OnTranslationSaveAllToggled (object o, EventArgs args) {
 		Base.Config.PrefsTranslationSaveAll = translationSaveAllCheckButton.Active;
 	}
+	
+	private void OnAutoBackupToggled (object o, EventArgs args) {
+		bool isActive = (o as CheckButton).Active;
+		
+		Base.Config.PrefsBackupAutoBackup = isActive;
+		autoBackupTimeSpinButton.Sensitive = isActive;
+		
+		Base.Backup.ReCheck();
+	}
+	
+	private void OnAutoBackupTimeSpinButonValueChanged (object o, EventArgs args) {
+		Base.Config.PrefsBackupBackupTime = (o as SpinButton).ValueAsInt * 60; //seconds
+		Base.Backup.ReCheck();
+	}
 
 	protected override bool ProcessResponse (ResponseType response) {
 		if (response == ResponseType.Cancel) {
diff --git a/src/SubLib/Core/Domain/FileProperties.cs b/src/SubLib/Core/Domain/FileProperties.cs
index 89ebc75..ff57757 100644
--- a/src/SubLib/Core/Domain/FileProperties.cs
+++ b/src/SubLib/Core/Domain/FileProperties.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of SubLib.
- * Copyright (C) 2007-2008 Pedro Castro
+ * Copyright (C) 2007-2010 Pedro Castro
  *
  * SubLib is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@ namespace SubLib.Core.Domain {
 
 /// <summary>Represents the properties of a file.</summary>
 /// <remarks>This includes all that's necessary to work with files, in relation to <see cref="Subtitles" />.</remarks>
-public class FileProperties {
+public class FileProperties : ICloneable {
 	/* Used for reading and writing */
 	private string path = String.Empty; //The path of the file
 	private Encoding encoding = null; //The character coding of the file
@@ -75,6 +75,9 @@ public class FileProperties {
 	public FileProperties (string path) : this(path, null, SubtitleType.Unknown, TimingMode.Times) {
 	}
 
+
+	/* Public properties */
+
 	/// <summary>The file's path.</summary>
 	public string Path {
 		get { return path; }
@@ -123,6 +126,13 @@ public class FileProperties {
 		get { return newlineType; }
 		set { newlineType = value; }
 	}
+	
+	
+	/* Public methods */
+	
+	public object Clone () {
+		return this.MemberwiseClone();
+	}
 
 }
 
diff --git a/src/SubLib/Core/Domain/Frames.cs b/src/SubLib/Core/Domain/Frames.cs
index 552512c..2d73a52 100644
--- a/src/SubLib/Core/Domain/Frames.cs
+++ b/src/SubLib/Core/Domain/Frames.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of SubLib.
- * Copyright (C) 2005-2009 Pedro Castro
+ * Copyright (C) 2005-2010 Pedro Castro
  *
  * SubLib is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,6 +31,8 @@ public class Frames {
 	private Subtitle subtitle = null;
 	
 	
+	/* Public properties */
+	
 	/// <summary>The start frame.</summary>
 	/// <remarks>Upon setting the start frame, the start time (<see cref="Times.Start">Times.Start</see>) is also updated based on
 	/// the <see cref="SubtitleProperties.CurrentFrameRate" />.</remarks>
@@ -62,6 +64,8 @@ public class Frames {
 		set { End = Start + value; }
 	}
 	
+	/* Public methods */
+	
 	/// <summary>Shifts the subtitle with a specified amount of frames.</summary>
 	/// <param name="frames">The number of frames to shift the subtitle with, which can be positive or negative.</param>
 	public void Shift (int frames) {
@@ -70,12 +74,18 @@ public class Frames {
 		subtitle.UpdateTimesFromFrames();
 	}
 	
-	
 	public override string ToString() {
   		return Start + "->" + End;
 	}
-	
-	/* Internal members */
+
+	public Frames Clone (Subtitle subtitleClone) {
+		Frames clone = this.MemberwiseClone() as Frames;
+		clone.SetFieldsForDeepClone(subtitleClone);
+		return clone;	
+	}
+
+
+		/* Internal members */
 		
 	internal Frames (Subtitle subtitle) {
 		this.subtitle = subtitle;
@@ -112,6 +122,12 @@ public class Frames {
 
 		subtitle.UpdateTimesFromFrames();	
 	}
+	
+	/* Private members */
+	
+	private void SetFieldsForDeepClone (Subtitle subtitle) {
+		this.subtitle = subtitle;
+	}
 
 }
 
diff --git a/src/SubLib/Core/Domain/Headers.cs b/src/SubLib/Core/Domain/Headers.cs
index cfd4827..ddc39ad 100644
--- a/src/SubLib/Core/Domain/Headers.cs
+++ b/src/SubLib/Core/Domain/Headers.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of SubLib.
- * Copyright (C) 2006-2008 Pedro Castro
+ * Copyright (C) 2006-2010 Pedro Castro
  *
  * SubLib is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@ using System.Text;
 namespace SubLib.Core.Domain {
 	
 /// <summary>Represents the headers of the supported subtitle formats.</summary>
-public class Headers {
+public class Headers : ICloneable {
 
 	private string title = String.Empty;
 	private string author = String.Empty;
@@ -57,6 +57,9 @@ public class Headers {
 	private int fontSize = 24;
 	private int delay = 0;
 	private int cdTrack = 0;
+
+	
+	/* Public properties */
 	
 	/// <summary>The movie's title.</summary>
 	public string Title {
@@ -320,6 +323,13 @@ public class Headers {
 			}
 		 }
 	}
+
+
+	/* Public methods */
+	
+	public object Clone () {
+		return this.MemberwiseClone();
+	}
 	
 }
 
diff --git a/src/SubLib/Core/Domain/Style.cs b/src/SubLib/Core/Domain/Style.cs
index 9e61f4c..c786693 100644
--- a/src/SubLib/Core/Domain/Style.cs
+++ b/src/SubLib/Core/Domain/Style.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of SubLib.
- * Copyright (C) 2005-2008 Pedro Castro
+ * Copyright (C) 2005-2010 Pedro Castro
  *
  * SubLib is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@ using System.Collections;
 namespace SubLib.Core.Domain {
 	
 /// <summary>Represents a text style, including Bold, Italic and Underline.</summary>
-public class Style {
+public class Style : ICloneable {
 	private bool bold = false;
 	private bool italic = false;
 	private bool underline = false;
@@ -42,6 +42,9 @@ public class Style {
 		this.italic = italic;
 		this.underline = underline;
 	}
+
+
+	/* Public properties */
 	
 	/// <summary>Whether the style is bold.</summary>
 	public bool Bold {
@@ -76,6 +79,13 @@ public class Style {
   			result += " underline";
   		return result;
 	}
+	
+	
+	/* Public methods */
+
+	public object Clone() {
+		return this.MemberwiseClone();
+	}
 
 }
 
diff --git a/src/SubLib/Core/Domain/Subtitle.cs b/src/SubLib/Core/Domain/Subtitle.cs
index a7ba2ea..5241ced 100644
--- a/src/SubLib/Core/Domain/Subtitle.cs
+++ b/src/SubLib/Core/Domain/Subtitle.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of SubLib.
- * Copyright (C) 2005-2009 Pedro Castro
+ * Copyright (C) 2005-2010 Pedro Castro
  *
  * SubLib is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -76,6 +76,12 @@ public class Subtitle {
 			: this(properties, new SubtitleText(), new Style()){
 	}
 	
+	private Subtitle () {
+	}
+	
+	
+	/* Public properties */
+	
 	/// <summary>The subtitle's text.</summary>
 	public SubtitleText Text {
 		get { return text; }
@@ -107,17 +113,36 @@ public class Subtitle {
 	public Frames Frames {
 		get { return frames; }
 	}
+	
+	/* Public methods */
+	
+	/// <summary></summary>
+	/// <remarks>SubtitleProperties is not cloned and should be set afterwards.</remarks>
+	public Subtitle Clone (SubtitleProperties propertiesClone) {
+		Subtitle subtitleClone = new Subtitle();
+		
+		Times timesClone = this.times.Clone(subtitleClone);
+		Frames framesClone = this.frames.Clone(subtitleClone);
+		SubtitleText textClone = this.text.Clone() as SubtitleText;
+		SubtitleText translationClone = (this.translation != null ? this.translation.Clone() as SubtitleText : null);
+		Style styleClone = this.style.Clone() as Style;
+		subtitleClone.SetFieldsForDeepClone(propertiesClone, timesClone, framesClone, textClone, translationClone, styleClone);
+		
+		return subtitleClone;
+	}
 		
 	public override string ToString () {
   		return "* " + Times + " (" + Frames + ") " + Style + "\n" + Text.ToString();
 	}
 	
+	
 	/* Internal properties */
 	
 	internal SubtitleProperties Properties {
 		set { properties = value; }
 	}
 	
+	
 	/* Internal methods */
 
 	internal void UpdateFramesFromTimes (float frameRate) {
@@ -175,6 +200,18 @@ public class Subtitle {
 	internal void ClearTranslation () {
 		translation = null;
 	}
+	
+	
+	/* Private methods */
+	
+	private void SetFieldsForDeepClone (SubtitleProperties properties, Times times, Frames frames, SubtitleText text, SubtitleText translation, Style style) {
+		this.properties = properties;
+		this.times = times;
+		this.frames = frames;
+		this.text = text;
+		this.translation = translation;
+		this.style = style;
+	}
 
 }
 
diff --git a/src/SubLib/Core/Domain/SubtitleCollection.cs b/src/SubLib/Core/Domain/SubtitleCollection.cs
index 47696ea..f8f19e6 100644
--- a/src/SubLib/Core/Domain/SubtitleCollection.cs
+++ b/src/SubLib/Core/Domain/SubtitleCollection.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of SubLib.
- * Copyright (C) 2005-2008 Pedro Castro
+ * Copyright (C) 2005-2010 Pedro Castro
  *
  * SubLib is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,18 +24,17 @@ namespace SubLib.Core.Domain {
 	
 /// <summary>A container that represents all the subtitles.</summary>
 public class SubtitleCollection {
-	private ArrayList subtitles = new ArrayList();
+	private ArrayList subtitles = new ArrayList(); 
+
+
+	/* Public properties */
 	
 	/// <summary>The number of subtitles in the collection.</summary>
 	public int Count {
 		get { return subtitles.Count; }
 	}
-	
-	/// <summary>Returns an enumerator that can iterate through the collection.</summary>
-	/// <returns>An <see cref="IEnumerator" /> for the entire <see cref="SubtitleCollection" />.</returns>
-	public IEnumerator GetEnumerator () {
-		return subtitles.GetEnumerator();
-	}
+
+	/* Indexers */
 	
 	public Subtitle this [int index] {
 		get {
@@ -47,6 +46,24 @@ public class SubtitleCollection {
 			}
 		}
 	}
+
+
+	/* Public methods */
+
+	public SubtitleCollection Clone (SubtitleProperties propertiesClone) {
+		SubtitleCollection collectionClone = new SubtitleCollection();
+		foreach (Subtitle subtitle in this.subtitles) {
+			Subtitle subtitleClone = subtitle.Clone(propertiesClone);
+			collectionClone.Add(subtitleClone);
+		}
+		return collectionClone;
+	}
+
+	/// <summary>Returns an enumerator that can iterate through the collection.</summary>
+	/// <returns>An <see cref="IEnumerator" /> for the entire <see cref="SubtitleCollection" />.</returns>
+	public IEnumerator GetEnumerator () {
+		return subtitles.GetEnumerator();
+	}
 	
 	/// <summary>Returns the subtitle at the specified index.</summary>
 	/// <param name="index">The zero-based subtitle's index.</param>
@@ -155,7 +172,8 @@ public class SubtitleCollection {
 		}
 		return result;
 	}
-	
+
+
 	/* Internal methods */
 	
 	internal void SetPropertiesForAll (SubtitleProperties properties) {
diff --git a/src/SubLib/Core/Domain/SubtitleProperties.cs b/src/SubLib/Core/Domain/SubtitleProperties.cs
index cea89b4..7b91fe0 100644
--- a/src/SubLib/Core/Domain/SubtitleProperties.cs
+++ b/src/SubLib/Core/Domain/SubtitleProperties.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of SubLib.
- * Copyright (C) 2005-2008 Pedro Castro
+ * Copyright (C) 2005-2010 Pedro Castro
  *
  * SubLib is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@ namespace SubLib.Core.Domain {
 /// <remarks>This class acts as a container which allows you to get and set a 
 /// variety of properties. Some of these properties are used in syncronization
 /// and timing calculations.</remarks>
-public class SubtitleProperties {
+public class SubtitleProperties : ICloneable {
 	private Headers headers = new Headers();
 	
 	private float originalFrameRate = 25;
@@ -52,6 +52,8 @@ public class SubtitleProperties {
 	}
 	
 	
+	/* Public properties */
+	
 	/// <summary>The headers used in some subtitle formats.</summary>
 	public Headers Headers {
 		get { return headers; }
@@ -71,10 +73,18 @@ public class SubtitleProperties {
 		get { return currentFrameRate; }
 	}
 	
+	
+	/* Public methods */
+	
 	public override string ToString () {
 		return "Original FPS = " + originalFrameRate + ", Current FPS = " + currentFrameRate + "\n" + headers.ToString();
 	}
 	
+	public object Clone() {
+		return new SubtitleProperties(this.Headers.Clone() as Headers, this.OriginalFrameRate, this.CurrentFrameRate);
+	}
+	
+	
 	/* Internal members */
 	
 	internal void SetCurrentFrameRate (float frameRate) {
diff --git a/src/SubLib/Core/Domain/SubtitleText.cs b/src/SubLib/Core/Domain/SubtitleText.cs
index ccee4ff..69c70de 100644
--- a/src/SubLib/Core/Domain/SubtitleText.cs
+++ b/src/SubLib/Core/Domain/SubtitleText.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of SubLib.
- * Copyright (C) 2005-2008 Pedro Castro
+ * Copyright (C) 2005-2010 Pedro Castro
  *
  * SubLib is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@ namespace SubLib.Core.Domain {
 
 //TODO this can be optimized
 /// <summary>Represents the text of a subtitle.</summary>	
-public class SubtitleText {
+public class SubtitleText : ICloneable {
 	private ArrayList lines = new ArrayList();
 
 	/// <summary>Initializes a new instance of the <see cref="SubtitleText" /> class
@@ -49,11 +49,17 @@ public class SubtitleText {
 	public SubtitleText() {
 	}
 	
+	
+	/* Public properties */
+	
 	/// <summary>Whether there is no text.</summary>
 	public bool IsEmpty {
 		get { return (lines.Count == 0); }
 	}
+
 	
+	/* Public methods */
+
 	/// <summary>Gets the specified text line.</summary>
 	/// <param name="index">The zero-based line number index.</param>
 	/// <returns>The specified text line.</returns>
@@ -181,6 +187,15 @@ public class SubtitleText {
   		return result;
 	}
 	
+	public object Clone() {
+		SubtitleText clone = new SubtitleText();
+		foreach (string line in lines) {
+			clone.lines.Add(line);
+		}
+		return clone;
+	}
+
+
 	/* Private Methods */
 	
 	private string ReplaceLineIfEmpty (string textLine, string replacement) {
diff --git a/src/SubLib/Core/Domain/Subtitles.cs b/src/SubLib/Core/Domain/Subtitles.cs
index 82df589..e4f587d 100644
--- a/src/SubLib/Core/Domain/Subtitles.cs
+++ b/src/SubLib/Core/Domain/Subtitles.cs
@@ -28,13 +28,16 @@ namespace SubLib.Core.Domain {
 
 /// <summary>Represents the root class of all the subtitles.</summary>
 /// <remarks>A <see cref="Subtitles" /> class is created using the <see cref="SubtitleFactory" />.</remarks>
-public class Subtitles {
+public class Subtitles : ICloneable {
 	private SubtitleCollection collection = null;
 	private SubtitleProperties properties = null;
 
 	/* Variable cache */
 	private static SubtitleTypeInfo[] availableTypes = null;
 	private static SubtitleTypeInfo[] availableTypesSorted = null;
+
+
+	/* Public properties */
 	
 	/// <summary>A collection which contains the subtitles.</summary>
 	public SubtitleCollection Collection {
@@ -74,6 +77,9 @@ public class Subtitles {
 			return availableTypesSorted;	
 		}
 	}
+
+
+	/* Public methods */
 	
 	/// <summary>Get information about an available subtitle type.</summary>
 	/// <param name="type">The subtitle type.</param>
@@ -91,12 +97,18 @@ public class Subtitles {
 		}
 		return false;
 	}
-
 	
 	public override string ToString(){
 		return Collection.ToString() + "\n-------------------------------------------\n" + Properties.ToString();
 	}
-	
+
+	public object Clone() {
+		SubtitleProperties propertiesClone = this.properties.Clone() as SubtitleProperties;
+		SubtitleCollection collectionClone = this.collection.Clone(propertiesClone);
+		return new Subtitles(collectionClone, propertiesClone);
+	}
+
+
 	/* Internal members */
 
 	/// <summary>Initializes a new instance of the <see cref="Subtitles" /> class.</summary>
diff --git a/src/SubLib/Core/Domain/Times.cs b/src/SubLib/Core/Domain/Times.cs
index f934c9e..5ea57aa 100644
--- a/src/SubLib/Core/Domain/Times.cs
+++ b/src/SubLib/Core/Domain/Times.cs
@@ -1,6 +1,6 @@
 /*
  * This file is part of SubLib.
- * Copyright (C) 2005-2009 Pedro Castro
+ * Copyright (C) 2005-2010 Pedro Castro
  *
  * SubLib is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@ public class Times {
 	private TimeSpan end = TimeSpan.Zero;
 	private Subtitle subtitle = null;
 
+	/* Public properties */
 
 	/// <summary>The start time.</summary>
 	/// <remarks>Upon setting the start time, the start frame (<see cref="Frames.Start">Frames.Start</see>) is also updated based on
@@ -61,6 +62,9 @@ public class Times {
 		get { return End - Start; }
 		set { End = Start + value; }
 	}
+	
+	
+	/* Public methods */
 
 	/// <summary>Shifts the subtitle with a specified time span.</summary>
 	/// <param name="time">The time span to shift the subtitle with, which can be positive or negative.</param>
@@ -78,6 +82,12 @@ public class Times {
 	public override string ToString() {
   		return Start + "->" + End;
 	}
+	
+	public Times Clone (Subtitle subtitleClone) {
+		Times clone = this.MemberwiseClone() as Times;
+		clone.SetFieldsForDeepClone(subtitleClone);
+		return clone;
+	}
 
 	
 	/* Internal members */
@@ -116,6 +126,13 @@ public class Times {
 
 		subtitle.UpdateFramesFromTimes();	
 	}
+	
+	
+	/* Private methods */
+	
+	private void SetFieldsForDeepClone (Subtitle subtitle) {
+		this.subtitle = subtitle;
+	}
 
 }
 



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