diff --git a/Duplicati/GUI/Backup defaults.xml b/Duplicati/GUI/Backup defaults.xml index d6bca8f68..4f1143afa 100644 --- a/Duplicati/GUI/Backup defaults.xml +++ b/Duplicati/GUI/Backup defaults.xml @@ -8,4 +8,5 @@ 13h e:.*\\Thumbs.db true + ' diff --git a/Duplicati/GUI/Database schema/2. Refactor for easier extensions.sql b/Duplicati/GUI/Database schema/2. Refactor for easier extensions.sql new file mode 100644 index 000000000..3bda651c7 --- /dev/null +++ b/Duplicati/GUI/Database schema/2. Refactor for easier extensions.sql @@ -0,0 +1,57 @@ +-- TaskSettings becomes BackendSetting +ALTER TABLE TaskSetting RENAME TO BackendSetting; + +-- TaskSetting is now extensions +CREATE TABLE "TaskExtension" ( + "ID" INTEGER PRIMARY KEY, + "TaskID" INTEGER NULL, + "Name" TEXT NULL, + "Value" TEXT NULL +); + +-- Copy values from the Task table +INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Max Upload Size', [MaxUploadSize] FROM Task; +INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Upload bandwidth', [UploadBandwidth] FROM Task; +INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Download Bandwidth', [DownloadBandwidth] FROM Task; +INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Volume Size', [VolumeSize] FROM Task; +INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Thread Priority', [ThreadPriority] FROM Task; +INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Async Transfer', [AsyncTransfer] FROM Task; +INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Include Setup', [IncludeSetup] FROM Task; +INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Ignore Timestamps', [IgnoreTimestamps] FROM Task; + +-- Move FileTimeSeperator into extensions +INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [TaskID], 'File Time Seperator', Value FROM BackendSetting WHERE [Name] = 'TimeSeparator'; +DELETE FROM BackendSetting WHERE [Name] = 'TimeSeparator'; + +-- Create a reduced Task table +CREATE TABLE "TempTask" ( + "ID" INTEGER PRIMARY KEY, + "ScheduleID" INTEGER NULL, + "Service" TEXT NULL, + "Encryptionkey" TEXT NULL, + "Signaturekey" TEXT NULL, + "SourcePath" TEXT NULL, + "KeepFull" INTEGER NULL, + "KeepTime" TEXT NULL, + "FullAfter" TEXT NULL, + "GPGEncryption" BOOLEAN NULL, + "IncludeSetup" BOOLEAN NULL +); + +-- Copy values +INSERT INTO TempTask ([ID], [ScheduleID], [Service], [EncryptionKey], [SignatureKey], [SourcePath], [KeepFull], [KeepTime], [FullAfter], [GPGEncryption], [IncludeSetup]) SELECT [ID], [ScheduleID], [Service], [EncryptionKey], [SignatureKey], [SourcePath], [KeepFull], [KeepTime], [FullAfter], [GPGEncryption], [IncludeSetup] FROM Task; +DROP TABLE Task; + +-- Use the new reduced table +ALTER TABLE "TempTask" RENAME TO "Task"; + +-- Add the override table +CREATE TABLE "TaskOverride" ( + "ID" INTEGER PRIMARY KEY, + "TaskID" INTEGER NULL, + "Name" TEXT NULL, + "Value" TEXT NULL +); + +-- Reduce database size +VACUUM; \ No newline at end of file diff --git a/Duplicati/GUI/Database schema/Schema.sql b/Duplicati/GUI/Database schema/Schema.sql index 2335f67cb..f9e62f239 100644 --- a/Duplicati/GUI/Database schema/Schema.sql +++ b/Duplicati/GUI/Database schema/Schema.sql @@ -1,22 +1,15 @@ CREATE TABLE "Task" ( "ID" INTEGER PRIMARY KEY, + "ScheduleID" INTEGER NULL, "Service" TEXT NULL, "Encryptionkey" TEXT NULL, "Signaturekey" TEXT NULL, "SourcePath" TEXT NULL, - "ScheduleID" INTEGER NULL, "KeepFull" INTEGER NULL, "KeepTime" TEXT NULL, - "MaxUploadsize" TEXT NULL, - "UploadBandwidth" TEXT NULL, - "DownloadBandwidth" TEXT NULL, - "VolumeSize" TEXT NULL, "FullAfter" TEXT NULL, - "ThreadPriority" TEXT NULL, - "AsyncTransfer" BOOLEAN NULL, "GPGEncryption" BOOLEAN NULL, - "IncludeSetup" BOOLEAN NULL, - "IgnoreTimestamps" BOOLEAN NULL + "IncludeSetup" BOOLEAN NULL ); CREATE TABLE "Schedule" ( @@ -28,8 +21,21 @@ CREATE TABLE "Schedule" ( "Weekdays" TEXT NULL ); +CREATE TABLE "BackendSetting" ( + "ID" INTEGER PRIMARY KEY, + "TaskID" INTEGER NULL, + "Name" TEXT NULL, + "Value" TEXT NULL +); -CREATE TABLE "TaskSetting" ( +CREATE TABLE "TaskExtension" ( + "ID" INTEGER PRIMARY KEY, + "TaskID" INTEGER NULL, + "Name" TEXT NULL, + "Value" TEXT NULL +); + +CREATE TABLE "TaskOverride" ( "ID" INTEGER PRIMARY KEY, "TaskID" INTEGER NULL, "Name" TEXT NULL, @@ -80,4 +86,4 @@ CREATE TABLE "TaskFilter" ( ); -INSERT INTO "Version" ("Version") VALUES (1); \ No newline at end of file +INSERT INTO "Version" ("Version") VALUES (2); \ No newline at end of file diff --git a/Duplicati/GUI/Datamodel/BackendSetting.cs b/Duplicati/GUI/Datamodel/BackendSetting.cs new file mode 100644 index 000000000..50172a8af --- /dev/null +++ b/Duplicati/GUI/Datamodel/BackendSetting.cs @@ -0,0 +1,92 @@ +#region Disclaimer / License +// Copyright (C) 2009, Kenneth Skovhede +// http://www.hexad.dk, opensource@hexad.dk +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +#endregion +/// +/// This class was created by DataClassFileBuilder (LightDatamodel) +/// +/// Table +/// Duplicati.Datamodel +/// BackendSetting +/// +/// + +using System.Data.LightDatamodel; +using System.Data.LightDatamodel.DataClassAttributes; + +namespace Duplicati.Datamodel +{ + + [DatabaseTable("BackendSetting")] + public partial class BackendSetting : DataClassBase + { + +#region " private members " + + [AutoIncrement, PrimaryKey, DatabaseField("ID")] + private System.Int64 m_ID = long.MinValue; + [Relation("BackendSettingTask", typeof(Task), "ID"), DatabaseField("TaskID")] + private System.Int64 m_TaskID = long.MinValue; + [DatabaseField("Name")] + private System.String m_Name = ""; + [DatabaseField("Value")] + private System.String m_Value = ""; +#endregion + +#region " properties " + + public System.Int64 ID + { + get{return m_ID;} + set{object oldvalue = m_ID;OnBeforeDataChange(this, "ID", oldvalue, value);m_ID = value;OnAfterDataChange(this, "ID", oldvalue, value);} + } + + public System.Int64 TaskID + { + get{return m_TaskID;} + set{object oldvalue = m_TaskID;OnBeforeDataChange(this, "TaskID", oldvalue, value);m_TaskID = value;OnAfterDataChange(this, "TaskID", oldvalue, value);} + } + + public System.String Name + { + get{return m_Name;} + set{object oldvalue = m_Name;OnBeforeDataChange(this, "Name", oldvalue, value);m_Name = value;OnAfterDataChange(this, "Name", oldvalue, value);} + } + + public System.String Value + { + get{return m_Value;} + set{object oldvalue = m_Value;OnBeforeDataChange(this, "Value", oldvalue, value);m_Value = value;OnAfterDataChange(this, "Value", oldvalue, value);} + } + +#endregion + +#region " referenced properties " + + [Affects(typeof(Task))] + public Task Task + { + get{ return ((DataFetcherWithRelations)m_dataparent).GetRelatedObject("BackendSettingTask", this); } + set{ ((DataFetcherWithRelations)m_dataparent).SetRelatedObject("BackendSettingTask", this, value); } + } + +#endregion + + } + +} \ No newline at end of file diff --git a/Duplicati/GUI/Datamodel/Backends/FTP.cs b/Duplicati/GUI/Datamodel/Backends/FTP.cs index 62e7a4165..e369606ad 100644 --- a/Duplicati/GUI/Datamodel/Backends/FTP.cs +++ b/Duplicati/GUI/Datamodel/Backends/FTP.cs @@ -42,20 +42,20 @@ namespace Duplicati.Datamodel.Backends public string Username { - get { return m_owner.Settings[USERNAME]; } - set { m_owner.Settings[USERNAME] = value; } + get { return m_owner.BackendSettingsLookup[USERNAME]; } + set { m_owner.BackendSettingsLookup[USERNAME] = value; } } public string Password { - get { return m_owner.Settings[PASSWORD]; } - set { m_owner.Settings[PASSWORD] = value; } + get { return m_owner.BackendSettingsLookup[PASSWORD]; } + set { m_owner.BackendSettingsLookup[PASSWORD] = value; } } public string Host { - get { return m_owner.Settings[HOST]; } - set { m_owner.Settings[HOST] = value; } + get { return m_owner.BackendSettingsLookup[HOST]; } + set { m_owner.BackendSettingsLookup[HOST] = value; } } public int Port @@ -63,29 +63,22 @@ namespace Duplicati.Datamodel.Backends get { int portn = 21; - int.TryParse(m_owner.Settings[PORT], out portn); + int.TryParse(m_owner.BackendSettingsLookup[PORT], out portn); return portn; } - set { m_owner.Settings[PORT] = value.ToString(); } + set { m_owner.BackendSettingsLookup[PORT] = value.ToString(); } } public string Folder { - get { return m_owner.Settings[FOLDER]; } - set { m_owner.Settings[FOLDER] = value; } + get { return m_owner.BackendSettingsLookup[FOLDER]; } + set { m_owner.BackendSettingsLookup[FOLDER] = value; } } public bool Passive { - get - { - bool res = false; - if (!bool.TryParse(m_owner.Settings[PASSIVE], out res)) - return true; - else - return res; - } - set { m_owner.Settings[PASSIVE] = value.ToString(); } + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.BackendSettingsLookup[PASSIVE], false); } + set { m_owner.BackendSettingsLookup[PASSIVE] = value.ToString(); } } #region IBackend Members diff --git a/Duplicati/GUI/Datamodel/Backends/File.cs b/Duplicati/GUI/Datamodel/Backends/File.cs index 3eb48efd3..7f59102de 100644 --- a/Duplicati/GUI/Datamodel/Backends/File.cs +++ b/Duplicati/GUI/Datamodel/Backends/File.cs @@ -27,8 +27,6 @@ namespace Duplicati.Datamodel.Backends public class File : IBackend { private const string DESTINATION_FOLDER = "Destination"; - private const string TIME_SEPARATOR = "TimeSeparator"; - private const string USERNAME = "Username"; private const string PASSWORD = "Password"; @@ -37,32 +35,26 @@ namespace Duplicati.Datamodel.Backends public File(Task owner) { m_owner = owner; - if (this.TimeSeparator == null) - this.TimeSeparator = "'"; + if (m_owner.Extensions.FileTimeSeperator == null) + m_owner.Extensions.FileTimeSeperator = "'"; } public string DestinationFolder { - get { return m_owner.Settings[DESTINATION_FOLDER]; } - set { m_owner.Settings[DESTINATION_FOLDER] = value; } - } - - public string TimeSeparator - { - get { return m_owner.Settings[TIME_SEPARATOR]; } - set { m_owner.Settings[TIME_SEPARATOR] = value; } + get { return m_owner.BackendSettingsLookup[DESTINATION_FOLDER]; } + set { m_owner.BackendSettingsLookup[DESTINATION_FOLDER] = value; } } public string Username { - get { return m_owner.Settings[USERNAME]; } - set { m_owner.Settings[USERNAME] = value; } + get { return m_owner.BackendSettingsLookup[USERNAME]; } + set { m_owner.BackendSettingsLookup[USERNAME] = value; } } public string Password { - get { return m_owner.Settings[PASSWORD]; } - set { m_owner.Settings[PASSWORD] = value; } + get { return m_owner.BackendSettingsLookup[PASSWORD]; } + set { m_owner.BackendSettingsLookup[PASSWORD] = value; } } #region IBackend Members @@ -77,7 +69,6 @@ namespace Duplicati.Datamodel.Backends public void GetOptions(Dictionary options) { - options["time-separator"] = this.TimeSeparator; if (!string.IsNullOrEmpty(this.Password)) options["ftp-password"] = this.Password; } diff --git a/Duplicati/GUI/Datamodel/Backends/S3.cs b/Duplicati/GUI/Datamodel/Backends/S3.cs index d86bb3d99..813ceff46 100644 --- a/Duplicati/GUI/Datamodel/Backends/S3.cs +++ b/Duplicati/GUI/Datamodel/Backends/S3.cs @@ -45,58 +45,44 @@ namespace Duplicati.Datamodel.Backends public string AccessID { - get { return m_owner.Settings[ACCESS_ID]; } - set { m_owner.Settings[ACCESS_ID] = value; } + get { return m_owner.BackendSettingsLookup[ACCESS_ID]; } + set { m_owner.BackendSettingsLookup[ACCESS_ID] = value; } } public string AccessKey { - get { return m_owner.Settings[ACCESS_KEY]; } - set { m_owner.Settings[ACCESS_KEY] = value; } + get { return m_owner.BackendSettingsLookup[ACCESS_KEY]; } + set { m_owner.BackendSettingsLookup[ACCESS_KEY] = value; } } public string BucketName { - get { return m_owner.Settings[BUCKET_NAME]; } - set { m_owner.Settings[BUCKET_NAME] = value; } + get { return m_owner.BackendSettingsLookup[BUCKET_NAME]; } + set { m_owner.BackendSettingsLookup[BUCKET_NAME] = value; } } public string ServerUrl { - get { return m_owner.Settings[SERVER_URL]; } - set { m_owner.Settings[SERVER_URL] = value; } + get { return m_owner.BackendSettingsLookup[SERVER_URL]; } + set { m_owner.BackendSettingsLookup[SERVER_URL] = value; } } public string Prefix { - get { return m_owner.Settings[PREFIX]; } - set { m_owner.Settings[PREFIX] = value; } + get { return m_owner.BackendSettingsLookup[PREFIX]; } + set { m_owner.BackendSettingsLookup[PREFIX] = value; } } public bool UseEuroBucket { - get - { - bool v; - if (bool.TryParse(m_owner.Settings[EUROBUCKET], out v)) - return v; - else - return false; - } - set { m_owner.Settings[EUROBUCKET] = value.ToString(); } + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.BackendSettingsLookup[EUROBUCKET], false); } + set { m_owner.BackendSettingsLookup[EUROBUCKET] = value.ToString(); } } public bool UseSubdomainStrategy { - get - { - bool v; - if (bool.TryParse(m_owner.Settings[SUBDOMAIN], out v)) - return v; - else - return false; - } - set { m_owner.Settings[SUBDOMAIN] = value.ToString(); } + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.BackendSettingsLookup[SUBDOMAIN], false); } + set { m_owner.BackendSettingsLookup[SUBDOMAIN] = value.ToString(); } } #region IBackend Members diff --git a/Duplicati/GUI/Datamodel/Backends/SSH.cs b/Duplicati/GUI/Datamodel/Backends/SSH.cs index 21e1e281e..eb881e98b 100644 --- a/Duplicati/GUI/Datamodel/Backends/SSH.cs +++ b/Duplicati/GUI/Datamodel/Backends/SSH.cs @@ -42,52 +42,45 @@ namespace Duplicati.Datamodel.Backends public string Username { - get { return m_owner.Settings[USERNAME]; } - set { m_owner.Settings[USERNAME] = value; } + get { return m_owner.BackendSettingsLookup[USERNAME]; } + set { m_owner.BackendSettingsLookup[USERNAME] = value; } } public string Password { - get { return m_owner.Settings[PASSWORD]; } - set { m_owner.Settings[PASSWORD] = value; } + get { return m_owner.BackendSettingsLookup[PASSWORD]; } + set { m_owner.BackendSettingsLookup[PASSWORD] = value; } } public string Host { - get { return m_owner.Settings[HOST]; } - set { m_owner.Settings[HOST] = value; } + get { return m_owner.BackendSettingsLookup[HOST]; } + set { m_owner.BackendSettingsLookup[HOST] = value; } } public int Port { get { - string port = m_owner.Settings[PORT]; + string port = m_owner.BackendSettingsLookup[PORT]; int portn; if (!int.TryParse(port, out portn)) portn = 22; return portn; } - set { m_owner.Settings[PORT] = value.ToString(); } + set { m_owner.BackendSettingsLookup[PORT] = value.ToString(); } } public string Folder { - get { return m_owner.Settings[FOLDER]; } - set { m_owner.Settings[FOLDER] = value; } + get { return m_owner.BackendSettingsLookup[FOLDER]; } + set { m_owner.BackendSettingsLookup[FOLDER] = value; } } public bool Passwordless { - get - { - bool v; - if (bool.TryParse(m_owner.Settings[PASWORDLESS], out v)) - return v; - else - return false; - } - set { m_owner.Settings[PASWORDLESS] = value.ToString(); } + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.BackendSettingsLookup[PASWORDLESS], false);} + set { m_owner.BackendSettingsLookup[PASWORDLESS] = value.ToString(); } } diff --git a/Duplicati/GUI/Datamodel/Backends/WEBDAV.cs b/Duplicati/GUI/Datamodel/Backends/WEBDAV.cs index 502e60a1a..ab5da85d9 100644 --- a/Duplicati/GUI/Datamodel/Backends/WEBDAV.cs +++ b/Duplicati/GUI/Datamodel/Backends/WEBDAV.cs @@ -1,3 +1,22 @@ +#region Disclaimer / License +// Copyright (C) 2009, Kenneth Skovhede +// http://www.hexad.dk, opensource@hexad.dk +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +#endregion using System; using System.Collections.Generic; using System.Text; @@ -24,20 +43,20 @@ namespace Duplicati.Datamodel.Backends public string Username { - get { return m_owner.Settings[USERNAME]; } - set { m_owner.Settings[USERNAME] = value; } + get { return m_owner.BackendSettingsLookup[USERNAME]; } + set { m_owner.BackendSettingsLookup[USERNAME] = value; } } public string Password { - get { return m_owner.Settings[PASSWORD]; } - set { m_owner.Settings[PASSWORD] = value; } + get { return m_owner.BackendSettingsLookup[PASSWORD]; } + set { m_owner.BackendSettingsLookup[PASSWORD] = value; } } public string Host { - get { return m_owner.Settings[HOST]; } - set { m_owner.Settings[HOST] = value; } + get { return m_owner.BackendSettingsLookup[HOST]; } + set { m_owner.BackendSettingsLookup[HOST] = value; } } public int Port @@ -45,42 +64,28 @@ namespace Duplicati.Datamodel.Backends get { int portn = 80; - int.TryParse(m_owner.Settings[PORT], out portn); + int.TryParse(m_owner.BackendSettingsLookup[PORT], out portn); return portn; } - set { m_owner.Settings[PORT] = value.ToString(); } + set { m_owner.BackendSettingsLookup[PORT] = value.ToString(); } } public string Folder { - get { return m_owner.Settings[FOLDER]; } - set { m_owner.Settings[FOLDER] = value; } + get { return m_owner.BackendSettingsLookup[FOLDER]; } + set { m_owner.BackendSettingsLookup[FOLDER] = value; } } public bool IntegratedAuthentication { - get - { - bool res = false; - if (!bool.TryParse(m_owner.Settings[INTEGRATED_AUTHENTICATION], out res)) - return false; - else - return res; - } - set { m_owner.Settings[INTEGRATED_AUTHENTICATION] = value.ToString(); } + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.BackendSettingsLookup[INTEGRATED_AUTHENTICATION] , false); } + set { m_owner.BackendSettingsLookup[INTEGRATED_AUTHENTICATION] = value.ToString(); } } public bool ForceDigestAuthentication { - get - { - bool res = false; - if (!bool.TryParse(m_owner.Settings[FORCE_DIGEST_AUTHENTICATION], out res)) - return false; - else - return res; - } - set { m_owner.Settings[FORCE_DIGEST_AUTHENTICATION] = value.ToString(); } + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.BackendSettingsLookup[FORCE_DIGEST_AUTHENTICATION] , false);} + set { m_owner.BackendSettingsLookup[FORCE_DIGEST_AUTHENTICATION] = value.ToString(); } } #region IBackend Members diff --git a/Duplicati/GUI/Datamodel/Datamodel.csproj b/Duplicati/GUI/Datamodel/Datamodel.csproj index 2ec641695..674f14141 100644 --- a/Duplicati/GUI/Datamodel/Datamodel.csproj +++ b/Duplicati/GUI/Datamodel/Datamodel.csproj @@ -1,120 +1 @@ - - - - Local - 8.0.50727 - 2.0 - {B60D0993-B0C5-457A-90D9-DB6EEB33CE47} - Debug - AnyCPU - - - Datamodel - LightDatamodel.snk - JScript - Grid - IE50 - false - Library - Duplicati.Datamodel - OnBuildSuccess - - - - true - - - bin\Debug\ - false - 285212672 - false - - - DEBUG;TRACE - - - true - 4096 - false - - - false - false - false - false - 4 - full - prompt - - - bin\Release\ - false - 285212672 - false - - - TRACE - - - false - 4096 - false - - - true - false - false - false - 4 - none - prompt - - - - System - - - System.Data - - - System.XML - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {CAE8433B-F013-474E-B7FC-4DE0D5933AD1} - LightDatamodel - - - {DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65} - Duplicati.Library.Core - - - - \ No newline at end of file +Local8.0.507272.0{B60D0993-B0C5-457A-90D9-DB6EEB33CE47}DebugAnyCPUDatamodelLightDatamodel.snkJScriptGridIE50falseLibraryDuplicati.DatamodelOnBuildSuccesstruebin\Debug\false285212672falseDEBUG;TRACEtrue4096falsefalsefalsefalsefalse4fullpromptbin\Release\false285212672falseTRACEfalse4096falsetruefalsefalsefalse4nonepromptSystemSystem.DataSystem.XML{CAE8433B-F013-474E-B7FC-4DE0D5933AD1}LightDatamodel{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}Duplicati.Library.Core \ No newline at end of file diff --git a/Duplicati/GUI/Datamodel/Duplicati.sqlite b/Duplicati/GUI/Datamodel/Duplicati.sqlite index 4296c957e..e5d9e34af 100644 Binary files a/Duplicati/GUI/Datamodel/Duplicati.sqlite and b/Duplicati/GUI/Datamodel/Duplicati.sqlite differ diff --git a/Duplicati/GUI/Datamodel/LightDataModel.Mapping.xml b/Duplicati/GUI/Datamodel/LightDataModel.Mapping.xml index 15be0c3f5..6e724e34d 100644 --- a/Duplicati/GUI/Datamodel/LightDataModel.Mapping.xml +++ b/Duplicati/GUI/Datamodel/LightDataModel.Mapping.xml @@ -94,50 +94,6 @@ false false - - System.String - MaxUploadsize - MaxUploadsize - false - false - false - false - false - false - - - System.String - UploadBandwidth - UploadBandwidth - false - false - false - false - false - false - - - System.String - DownloadBandwidth - DownloadBandwidth - false - false - false - false - false - false - - - System.String - VolumeSize - VolumeSize - false - false - false - false - false - false - System.String FullAfter @@ -149,28 +105,6 @@ false false - - System.String - ThreadPriority - ThreadPriority - false - false - false - false - false - false - - - System.Boolean - AsyncTransfer - AsyncTransfer - false - false - false - false - false - false - System.Boolean GPGEncryption @@ -193,17 +127,6 @@ false false - - System.Boolean - IgnoreTimestamps - IgnoreTimestamps - false - false - false - false - false - false - false @@ -294,70 +217,6 @@ false - - TaskSetting - TaskSetting - ID - - - System.Int64 - ID - ID - true - true - false - false - false - true - - - System.Int64 - TaskID - TaskID - false - false - false - false - false - false - - - System.String - Name - Name - false - false - false - false - false - false - - - System.String - Value - Value - false - false - false - false - false - false - - - false - - - TaskSettingTask - TaskID - Task - OneToMany - Task - ID - TaskSettings - TaskSetting - - -
CommandQueueCommandQueue @@ -719,5 +578,197 @@
+ + BackendSetting + BackendSetting + ID + + + System.Int64 + ID + ID + true + true + false + false + false + true + + + System.Int64 + TaskID + TaskID + false + false + false + false + false + false + + + System.String + Name + Name + false + false + false + false + false + false + + + System.String + Value + Value + false + false + false + false + false + false + + + false + + + BackendSettingTask + TaskID + Task + OneToMany + Task + ID + BackendSettings + BackendSetting + + +
+ + TaskExtension + TaskExtension + ID + + + System.Int64 + ID + ID + true + true + false + false + false + true + + + System.Int64 + TaskID + TaskID + false + false + false + false + false + false + + + System.String + Name + Name + false + false + false + false + false + false + + + System.String + Value + Value + false + false + false + false + false + false + + + false + + + TaskExtensionTask + TaskID + Task + OneToMany + Task + ID + TaskExtensions + TaskExtension + + +
+ + TaskOverride + TaskOverride + ID + + + System.Int64 + ID + ID + true + true + false + false + false + true + + + System.Int64 + TaskID + TaskID + false + false + false + false + false + false + + + System.String + Name + Name + false + false + false + false + false + false + + + System.String + Value + Value + false + false + false + false + false + false + + + false + + + TaskOverrideTask + TaskID + Task + OneToMany + Task + ID + TaskOverrides + TaskOverride + + +
\ No newline at end of file diff --git a/Duplicati/GUI/Datamodel/LightDatamodel.dll b/Duplicati/GUI/Datamodel/LightDatamodel.dll index 5e4aecafd..04157b111 100644 Binary files a/Duplicati/GUI/Datamodel/LightDatamodel.dll and b/Duplicati/GUI/Datamodel/LightDatamodel.dll differ diff --git a/Duplicati/GUI/Datamodel/Schedule.cs b/Duplicati/GUI/Datamodel/Schedule.cs index d7ee6fa3a..d334c772d 100644 --- a/Duplicati/GUI/Datamodel/Schedule.cs +++ b/Duplicati/GUI/Datamodel/Schedule.cs @@ -17,92 +17,92 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #endregion -/// -/// This class was created by DataClassFileBuilder (LightDatamodel) -/// -/// Table -/// Duplicati.Datamodel -/// Schedule -/// -/// - -using System.Data.LightDatamodel; -using System.Data.LightDatamodel.DataClassAttributes; - -namespace Duplicati.Datamodel -{ - - [DatabaseTable("Schedule")] - public partial class Schedule : DataClassBase - { - -#region " private members " - - [AutoIncrement, PrimaryKey, Relation("TaskSchedule", typeof(Task), "ScheduleID", false), DatabaseField("ID")] - private System.Int64 m_ID = long.MinValue; - [DatabaseField("Name")] - private System.String m_Name = ""; - [DatabaseField("Path")] - private System.String m_Path = ""; - [DatabaseField("When")] - private System.DateTime m_When = new System.DateTime(1, 1, 1); - [DatabaseField("Repeat")] - private System.String m_Repeat = ""; - [DatabaseField("Weekdays")] - private System.String m_Weekdays = ""; -#endregion - -#region " properties " - - public System.Int64 ID - { - get{return m_ID;} - set{object oldvalue = m_ID;OnBeforeDataChange(this, "ID", oldvalue, value);m_ID = value;OnAfterDataChange(this, "ID", oldvalue, value);} - } - - public System.String Name - { - get{return m_Name;} - set{object oldvalue = m_Name;OnBeforeDataChange(this, "Name", oldvalue, value);m_Name = value;OnAfterDataChange(this, "Name", oldvalue, value);} - } - - public System.String Path - { - get{return m_Path;} - set{object oldvalue = m_Path;OnBeforeDataChange(this, "Path", oldvalue, value);m_Path = value;OnAfterDataChange(this, "Path", oldvalue, value);} - } - - public System.DateTime When - { - get{return m_When;} - set{object oldvalue = m_When;OnBeforeDataChange(this, "When", oldvalue, value);m_When = value;OnAfterDataChange(this, "When", oldvalue, value);} - } - - public System.String Repeat - { - get{return m_Repeat;} - set{object oldvalue = m_Repeat;OnBeforeDataChange(this, "Repeat", oldvalue, value);m_Repeat = value;OnAfterDataChange(this, "Repeat", oldvalue, value);} - } - - public System.String Weekdays - { - get{return m_Weekdays;} - set{object oldvalue = m_Weekdays;OnBeforeDataChange(this, "Weekdays", oldvalue, value);m_Weekdays = value;OnAfterDataChange(this, "Weekdays", oldvalue, value);} - } - -#endregion - -#region " referenced properties " - - [Affects(typeof(Task))] - public Task Task - { - get{ return ((DataFetcherWithRelations)m_dataparent).GetRelatedObject("TaskSchedule", this); } - set{ ((DataFetcherWithRelations)m_dataparent).SetRelatedObject("TaskSchedule", this, value); } - } - -#endregion - - } - +/// +/// This class was created by DataClassFileBuilder (LightDatamodel) +/// +/// Table +/// Duplicati.Datamodel +/// Schedule +/// +/// + +using System.Data.LightDatamodel; +using System.Data.LightDatamodel.DataClassAttributes; + +namespace Duplicati.Datamodel +{ + + [DatabaseTable("Schedule")] + public partial class Schedule : DataClassBase + { + +#region " private members " + + [AutoIncrement, PrimaryKey, Relation("TaskSchedule", typeof(Task), "ScheduleID", false), DatabaseField("ID")] + private System.Int64 m_ID = long.MinValue; + [DatabaseField("Name")] + private System.String m_Name = ""; + [DatabaseField("Path")] + private System.String m_Path = ""; + [DatabaseField("When")] + private System.DateTime m_When = new System.DateTime(1, 1, 1); + [DatabaseField("Repeat")] + private System.String m_Repeat = ""; + [DatabaseField("Weekdays")] + private System.String m_Weekdays = ""; +#endregion + +#region " properties " + + public System.Int64 ID + { + get{return m_ID;} + set{object oldvalue = m_ID;OnBeforeDataChange(this, "ID", oldvalue, value);m_ID = value;OnAfterDataChange(this, "ID", oldvalue, value);} + } + + public System.String Name + { + get{return m_Name;} + set{object oldvalue = m_Name;OnBeforeDataChange(this, "Name", oldvalue, value);m_Name = value;OnAfterDataChange(this, "Name", oldvalue, value);} + } + + public System.String Path + { + get{return m_Path;} + set{object oldvalue = m_Path;OnBeforeDataChange(this, "Path", oldvalue, value);m_Path = value;OnAfterDataChange(this, "Path", oldvalue, value);} + } + + public System.DateTime When + { + get{return m_When;} + set{object oldvalue = m_When;OnBeforeDataChange(this, "When", oldvalue, value);m_When = value;OnAfterDataChange(this, "When", oldvalue, value);} + } + + public System.String Repeat + { + get{return m_Repeat;} + set{object oldvalue = m_Repeat;OnBeforeDataChange(this, "Repeat", oldvalue, value);m_Repeat = value;OnAfterDataChange(this, "Repeat", oldvalue, value);} + } + + public System.String Weekdays + { + get{return m_Weekdays;} + set{object oldvalue = m_Weekdays;OnBeforeDataChange(this, "Weekdays", oldvalue, value);m_Weekdays = value;OnAfterDataChange(this, "Weekdays", oldvalue, value);} + } + +#endregion + +#region " referenced properties " + + [Affects(typeof(Task))] + public Task Task + { + get{ return ((DataFetcherWithRelations)m_dataparent).GetRelatedObject("TaskSchedule", this); } + set{ ((DataFetcherWithRelations)m_dataparent).SetRelatedObject("TaskSchedule", this, value); } + } + +#endregion + + } + } \ No newline at end of file diff --git a/Duplicati/GUI/Datamodel/SettingsHelper.cs b/Duplicati/GUI/Datamodel/SettingsHelper.cs index c1c5dd149..e027ef332 100644 --- a/Duplicati/GUI/Datamodel/SettingsHelper.cs +++ b/Duplicati/GUI/Datamodel/SettingsHelper.cs @@ -35,7 +35,6 @@ namespace Duplicati.Datamodel private PropertyInfo m_keyfield; private PropertyInfo m_valuefield; - private TranslatoryEnumerator m_enum; public SettingsHelper(IDataFetcher parent, IList col, string keyfield, string valuefield) : this(parent, col, typeof(TBase).GetProperty(keyfield), typeof(TBase).GetProperty(valuefield)) @@ -59,17 +58,36 @@ namespace Duplicati.Datamodel if (m_valuefield == null) throw new ArgumentNullException("valuefield"); - m_settings = new Dictionary(); - m_enum = new TranslatoryEnumerator(this, m_settings.GetEnumerator()); + parent.AfterDataConnection += new DataConnectionEventHandler(parent_AfterDataConnection); + } + + void parent_AfterDataConnection(object sender, DataActions action) + { + if (action != DataActions.Fetch) + m_settings = null; - foreach (TBase item in m_col) - if (!m_settings.ContainsKey((TKey)m_keyfield.GetValue(item, null))) - m_settings.Add((TKey)m_keyfield.GetValue(item, null), item); } public PropertyInfo KeyField { get { return m_keyfield; } } public PropertyInfo ValueField { get { return m_valuefield; } } + private Dictionary InternalSettings + { + get + { + if (m_settings == null) + { + m_settings = new Dictionary(); + + foreach (TBase item in m_col) + if (!m_settings.ContainsKey((TKey)m_keyfield.GetValue(item, null))) + m_settings.Add((TKey)m_keyfield.GetValue(item, null), item); + } + + return m_settings; + } + } + #region IDictionary Members public void Add(TKey key, TValue value) @@ -78,36 +96,36 @@ namespace Duplicati.Datamodel m_keyfield.SetValue(item, key, null); m_valuefield.SetValue(item, value, null); - m_settings.Add(key, item); + InternalSettings.Add(key, item); m_parent.Add(item); m_col.Add(item); } public bool ContainsKey(TKey key) { - return m_settings.ContainsKey(key); + return InternalSettings.ContainsKey(key); } public ICollection Keys { - get { return m_settings.Keys; } + get { return InternalSettings.Keys; } } public bool Remove(TKey key) { - if (m_settings.ContainsKey(key)) + if (InternalSettings.ContainsKey(key)) { - m_col.Remove(m_settings[key]); - m_parent.DeleteObject(m_settings[key]); + m_col.Remove(InternalSettings[key]); + m_parent.DeleteObject(InternalSettings[key]); } - return m_settings.Remove(key); + return InternalSettings.Remove(key); } public bool TryGetValue(TKey key, out TValue value) { TBase item; - if (m_settings.TryGetValue(key, out item)) + if (InternalSettings.TryGetValue(key, out item)) { value = (TValue)m_valuefield.GetValue(item, null); return true; @@ -125,7 +143,7 @@ namespace Duplicati.Datamodel get { List lst = new List(); - foreach (TBase item in m_settings.Values) + foreach (TBase item in InternalSettings.Values) lst.Add((TValue)m_valuefield.GetValue(item, null)); return lst; } @@ -135,27 +153,27 @@ namespace Duplicati.Datamodel { get { - if (m_settings.ContainsKey(key)) - return (TValue)m_valuefield.GetValue(m_settings[key], null); + if (InternalSettings.ContainsKey(key)) + return (TValue)m_valuefield.GetValue(InternalSettings[key], null); else return default(TValue); } set { - if (value == null && m_settings.ContainsKey(key)) + if (value == null && InternalSettings.ContainsKey(key)) { //Remove this.Remove(key); } - else if (value != null && !m_settings.ContainsKey(key)) + else if (value != null && !InternalSettings.ContainsKey(key)) { //Add this.Add(key, value); } - else if (value != null && m_settings.ContainsKey(key)) + else if (value != null && InternalSettings.ContainsKey(key)) { //Update - m_valuefield.SetValue(m_settings[key], value, null); + m_valuefield.SetValue(InternalSettings[key], value, null); } //else: It should be removed, but does not exist @@ -180,7 +198,7 @@ namespace Duplicati.Datamodel m_parent.DeleteObject(item); } - m_settings.Clear(); + InternalSettings.Clear(); } public bool Contains(KeyValuePair item) @@ -190,12 +208,12 @@ namespace Duplicati.Datamodel public void CopyTo(KeyValuePair[] array, int arrayIndex) { - ((ICollection>)(m_settings)).CopyTo(array, arrayIndex); + ((ICollection>)(InternalSettings)).CopyTo(array, arrayIndex); } public int Count { - get { return m_settings.Count; } + get { return InternalSettings.Count; } } public bool IsReadOnly @@ -214,7 +232,7 @@ namespace Duplicati.Datamodel public IEnumerator> GetEnumerator() { - return m_enum; + return new TranslatoryEnumerator(this, InternalSettings.GetEnumerator()); } #endregion @@ -223,7 +241,7 @@ namespace Duplicati.Datamodel System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { - return ((System.Collections.IEnumerable)m_settings).GetEnumerator(); + return ((System.Collections.IEnumerable)InternalSettings).GetEnumerator(); } #endregion @@ -281,5 +299,8 @@ namespace Duplicati.Datamodel #endregion } + + public IDataFetcher DataParent { get { return m_parent; } } + public IList Collection { get { return m_col; } } } } diff --git a/Duplicati/GUI/Datamodel/Task.Extension.cs b/Duplicati/GUI/Datamodel/Task.Extension.cs index c91667eb4..463e96c21 100644 --- a/Duplicati/GUI/Datamodel/Task.Extension.cs +++ b/Duplicati/GUI/Datamodel/Task.Extension.cs @@ -27,19 +27,52 @@ namespace Duplicati.Datamodel { public partial class Task { - private SettingsHelper m_settings; + public Task() + { + this.AfterDataCommit += new System.Data.LightDatamodel.DataConnectionEventHandler(Task_AfterDataCommit); + } - public IDictionary Settings + void Task_AfterDataCommit(object sender, System.Data.LightDatamodel.DataActions action) + { + if (action != System.Data.LightDatamodel.DataActions.Fetch) + { + m_backendSettings = null; + m_extensionSettings = null; + } + } + + private SettingsHelper m_backendSettings; + private SettingsHelper m_extensionSettings; + + public IDictionary BackendSettingsLookup { get { - if (m_settings == null) - m_settings = new SettingsHelper(this.DataParent, this.TaskSettings, "Name", "Value"); + //Extra check because the datamodel copies the collection between contexts... not nice + if (m_backendSettings == null || m_backendSettings.DataParent != this.DataParent || m_backendSettings.Collection != this.BackendSettings) + m_backendSettings = new SettingsHelper(this.DataParent, this.BackendSettings, "Name", "Value"); - return m_settings; + return m_backendSettings; } } + public IDictionary TaskExtensionsLookup + { + get + { + //Extra check because the datamodel copies the collection between contexts... not nice + if (m_extensionSettings == null || m_extensionSettings.DataParent != this.DataParent || m_extensionSettings.Collection != this.TaskExtensions) + m_extensionSettings = new SettingsHelper(this.DataParent, this.TaskExtensions, "Name", "Value"); + + return m_extensionSettings; + } + } + + public TaskExtensionWrapper Extensions + { + get { return new TaskExtensionWrapper(this); } + } + public Backends.IBackend Backend { get @@ -74,18 +107,6 @@ namespace Duplicati.Datamodel if (this.Filters.Count > 0) options["filter"] = this.EncodedFilter; ; - if (!string.IsNullOrEmpty(this.MaxUploadsize)) - options["totalsize"] = this.MaxUploadsize; - if (!string.IsNullOrEmpty(this.VolumeSize)) - options["volsize"] = this.VolumeSize; - if (!string.IsNullOrEmpty(this.DownloadBandwidth)) - options["max-download-pr-second"] = this.DownloadBandwidth; - if (!string.IsNullOrEmpty(this.UploadBandwidth)) - options["max-upload-pr-second"] = this.UploadBandwidth; - if (!string.IsNullOrEmpty(this.ThreadPriority)) - options["thread-priority"] = this.ThreadPriority; - if (this.AsyncTransfer) - options["asynchronous-upload"] = ""; if (this.GPGEncryption) { options["gpg-encryption"] = ""; @@ -101,8 +122,11 @@ namespace Duplicati.Datamodel if (!string.IsNullOrEmpty(set.TempPath)) options["tempdir"] = System.Environment.ExpandEnvironmentVariables(set.TempPath); - if (this.IgnoreTimestamps) - options["disable-filetime-check"] = ""; + this.Extensions.GetOptions(options); + + //Override everything set in the overrides + foreach (TaskOverride ov in this.TaskOverrides) + options[ov.Name] = ov.Value; } public string EncodedFilter @@ -124,7 +148,7 @@ namespace Duplicati.Datamodel this.SortedFilters = new TaskFilter[0]; List filters = new List(); - foreach(KeyValuePair f in Library.Core.FilenameFilter.DecodeFilter(value)) + foreach (KeyValuePair f in Library.Core.FilenameFilter.DecodeFilter(value)) { TaskFilter tf = this.DataParent.Add(); tf.Filter = f.Value; @@ -165,5 +189,120 @@ namespace Duplicati.Datamodel } } + + public class TaskExtensionWrapper + { + private const string MAX_UPLOAD_SIZE = "Max Upload Size"; + private const string UPLOAD_BANDWIDTH = "Upload Bandwidth"; + private const string DOWNLOAD_BANDWIDTH = "Download Bandwidth"; + private const string VOLUME_SIZE = "Volume Size"; + private const string THREAD_PRIORITY = "Thread Priority"; + private const string ASYNC_TRANSFER = "Async Transfer"; + private const string INCLUDE_SETUP = "Include Setup"; + private const string IGNORE_TIMESTAMPS = "Ignore Timestamps"; + private const string FILE_SIZE_LIMIT = "File Size Limit"; + private const string FILE_TIME_SEPERATOR = "File Time Seperator"; + private const string SHORT_FILENAMES = "Short Filenames"; + private const string FILENAME_PREFIX = "Filename Prefix"; + + private Task m_owner; + + public TaskExtensionWrapper(Task owner) + { + m_owner = owner; + } + + public string MaxUploadSize + { + get { return m_owner.TaskExtensionsLookup[MAX_UPLOAD_SIZE]; } + set { m_owner.TaskExtensionsLookup[MAX_UPLOAD_SIZE] = value; } + } + + public string UploadBandwidth + { + get { return m_owner.TaskExtensionsLookup[UPLOAD_BANDWIDTH]; } + set { m_owner.TaskExtensionsLookup[UPLOAD_BANDWIDTH] = value; } + } + + public string DownloadBandwidth + { + get { return m_owner.TaskExtensionsLookup[DOWNLOAD_BANDWIDTH]; } + set { m_owner.TaskExtensionsLookup[DOWNLOAD_BANDWIDTH] = value; } + } + + public string VolumeSize + { + get { return m_owner.TaskExtensionsLookup[VOLUME_SIZE]; } + set { m_owner.TaskExtensionsLookup[VOLUME_SIZE] = value; } + } + + public string ThreadPriority + { + get { return m_owner.TaskExtensionsLookup[THREAD_PRIORITY]; } + set { m_owner.TaskExtensionsLookup[THREAD_PRIORITY] = value; } + } + + public bool AsyncTransfer + { + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[ASYNC_TRANSFER], false); } + set { m_owner.TaskExtensionsLookup[ASYNC_TRANSFER] = value.ToString(); } + } + + public bool IncludeSetup + { + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[INCLUDE_SETUP], true); } + set { m_owner.TaskExtensionsLookup[INCLUDE_SETUP] = value.ToString(); } + } + + public bool IgnoreTimestamps + { + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[IGNORE_TIMESTAMPS], true); } + set { m_owner.TaskExtensionsLookup[IGNORE_TIMESTAMPS] = value.ToString(); } + } + + public string FileSizeLimit + { + get { return m_owner.TaskExtensionsLookup[FILE_SIZE_LIMIT]; } + set { m_owner.TaskExtensionsLookup[FILE_SIZE_LIMIT] = value; } + } + + public string FileTimeSeperator + { + get { return m_owner.TaskExtensionsLookup[FILE_TIME_SEPERATOR]; } + set { m_owner.TaskExtensionsLookup[FILE_TIME_SEPERATOR] = value; } + } + + public bool ShortFilenames + { + get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SHORT_FILENAMES], false); } + set { m_owner.TaskExtensionsLookup[SHORT_FILENAMES] = value.ToString(); } + } + + public string FilenamePrefix + { + get { return m_owner.TaskExtensionsLookup[FILENAME_PREFIX]; } + set { m_owner.TaskExtensionsLookup[FILENAME_PREFIX] = value; } + } + + public void GetOptions(Dictionary options) + { + if (!string.IsNullOrEmpty(this.MaxUploadSize)) + options["totalsize"] = this.MaxUploadSize; + if (!string.IsNullOrEmpty(this.VolumeSize)) + options["volsize"] = this.VolumeSize; + if (!string.IsNullOrEmpty(this.DownloadBandwidth)) + options["max-download-pr-second"] = this.DownloadBandwidth; + if (!string.IsNullOrEmpty(this.UploadBandwidth)) + options["max-upload-pr-second"] = this.UploadBandwidth; + if (!string.IsNullOrEmpty(this.ThreadPriority)) + options["thread-priority"] = this.ThreadPriority; + if (this.AsyncTransfer) + options["asynchronous-upload"] = ""; + if (this.IgnoreTimestamps) + options["disable-filetime-check"] = ""; + if (!string.IsNullOrEmpty(this.FileTimeSeperator)) + options["time-separator"] = this.FileTimeSeperator; + } } + } } diff --git a/Duplicati/GUI/Datamodel/Task.cs b/Duplicati/GUI/Datamodel/Task.cs index 829e3dd0d..39b84d32e 100644 --- a/Duplicati/GUI/Datamodel/Task.cs +++ b/Duplicati/GUI/Datamodel/Task.cs @@ -38,7 +38,7 @@ namespace Duplicati.Datamodel #region " private members " - [AutoIncrement, PrimaryKey, Relation("TaskSettingTask", typeof(TaskSetting), "TaskID", false), Relation("LogTask", typeof(Log), "TaskID", false), Relation("TaskFilterTask", typeof(TaskFilter), "TaskID", false), DatabaseField("ID")] + [AutoIncrement, PrimaryKey, Relation("LogTask", typeof(Log), "TaskID", false), Relation("TaskFilterTask", typeof(TaskFilter), "TaskID", false), Relation("BackendSettingTask", typeof(BackendSetting), "TaskID", false), Relation("TaskExtensionTask", typeof(TaskExtension), "TaskID", false), Relation("TaskOverrideTask", typeof(TaskOverride), "TaskID", false), DatabaseField("ID")] private System.Int64 m_ID = long.MinValue; [DatabaseField("Service")] private System.String m_Service = ""; @@ -54,26 +54,12 @@ namespace Duplicati.Datamodel private System.Int64 m_KeepFull = long.MinValue; [DatabaseField("KeepTime")] private System.String m_KeepTime = ""; - [DatabaseField("MaxUploadsize")] - private System.String m_MaxUploadsize = ""; - [DatabaseField("UploadBandwidth")] - private System.String m_UploadBandwidth = ""; - [DatabaseField("DownloadBandwidth")] - private System.String m_DownloadBandwidth = ""; - [DatabaseField("VolumeSize")] - private System.String m_VolumeSize = ""; [DatabaseField("FullAfter")] private System.String m_FullAfter = ""; - [DatabaseField("ThreadPriority")] - private System.String m_ThreadPriority = ""; - [DatabaseField("AsyncTransfer")] - private System.Boolean m_AsyncTransfer = false; [DatabaseField("GPGEncryption")] private System.Boolean m_GPGEncryption = false; [DatabaseField("IncludeSetup")] private System.Boolean m_IncludeSetup = false; - [DatabaseField("IgnoreTimestamps")] - private System.Boolean m_IgnoreTimestamps = false; #endregion #region " properties " @@ -126,48 +112,12 @@ namespace Duplicati.Datamodel set{object oldvalue = m_KeepTime;OnBeforeDataChange(this, "KeepTime", oldvalue, value);m_KeepTime = value;OnAfterDataChange(this, "KeepTime", oldvalue, value);} } - public System.String MaxUploadsize - { - get{return m_MaxUploadsize;} - set{object oldvalue = m_MaxUploadsize;OnBeforeDataChange(this, "MaxUploadsize", oldvalue, value);m_MaxUploadsize = value;OnAfterDataChange(this, "MaxUploadsize", oldvalue, value);} - } - - public System.String UploadBandwidth - { - get{return m_UploadBandwidth;} - set{object oldvalue = m_UploadBandwidth;OnBeforeDataChange(this, "UploadBandwidth", oldvalue, value);m_UploadBandwidth = value;OnAfterDataChange(this, "UploadBandwidth", oldvalue, value);} - } - - public System.String DownloadBandwidth - { - get{return m_DownloadBandwidth;} - set{object oldvalue = m_DownloadBandwidth;OnBeforeDataChange(this, "DownloadBandwidth", oldvalue, value);m_DownloadBandwidth = value;OnAfterDataChange(this, "DownloadBandwidth", oldvalue, value);} - } - - public System.String VolumeSize - { - get{return m_VolumeSize;} - set{object oldvalue = m_VolumeSize;OnBeforeDataChange(this, "VolumeSize", oldvalue, value);m_VolumeSize = value;OnAfterDataChange(this, "VolumeSize", oldvalue, value);} - } - public System.String FullAfter { get{return m_FullAfter;} set{object oldvalue = m_FullAfter;OnBeforeDataChange(this, "FullAfter", oldvalue, value);m_FullAfter = value;OnAfterDataChange(this, "FullAfter", oldvalue, value);} } - public System.String ThreadPriority - { - get{return m_ThreadPriority;} - set{object oldvalue = m_ThreadPriority;OnBeforeDataChange(this, "ThreadPriority", oldvalue, value);m_ThreadPriority = value;OnAfterDataChange(this, "ThreadPriority", oldvalue, value);} - } - - public System.Boolean AsyncTransfer - { - get{return m_AsyncTransfer;} - set{object oldvalue = m_AsyncTransfer;OnBeforeDataChange(this, "AsyncTransfer", oldvalue, value);m_AsyncTransfer = value;OnAfterDataChange(this, "AsyncTransfer", oldvalue, value);} - } - public System.Boolean GPGEncryption { get{return m_GPGEncryption;} @@ -180,12 +130,6 @@ namespace Duplicati.Datamodel set{object oldvalue = m_IncludeSetup;OnBeforeDataChange(this, "IncludeSetup", oldvalue, value);m_IncludeSetup = value;OnAfterDataChange(this, "IncludeSetup", oldvalue, value);} } - public System.Boolean IgnoreTimestamps - { - get{return m_IgnoreTimestamps;} - set{object oldvalue = m_IgnoreTimestamps;OnBeforeDataChange(this, "IgnoreTimestamps", oldvalue, value);m_IgnoreTimestamps = value;OnAfterDataChange(this, "IgnoreTimestamps", oldvalue, value);} - } - #endregion #region " referenced properties " @@ -197,15 +141,6 @@ namespace Duplicati.Datamodel set{ ((DataFetcherWithRelations)m_dataparent).SetRelatedObject("TaskSchedule", this, value); } } - [Affects(typeof(TaskSetting))] - public System.Collections.Generic.IList TaskSettings - { - get - { - return ((DataFetcherWithRelations)m_dataparent).GetRelatedObjects("TaskSettingTask", this); - } - } - [Affects(typeof(Log))] public System.Collections.Generic.IList Logs { @@ -224,6 +159,33 @@ namespace Duplicati.Datamodel } } + [Affects(typeof(BackendSetting))] + public System.Collections.Generic.IList BackendSettings + { + get + { + return ((DataFetcherWithRelations)m_dataparent).GetRelatedObjects("BackendSettingTask", this); + } + } + + [Affects(typeof(TaskExtension))] + public System.Collections.Generic.IList TaskExtensions + { + get + { + return ((DataFetcherWithRelations)m_dataparent).GetRelatedObjects("TaskExtensionTask", this); + } + } + + [Affects(typeof(TaskOverride))] + public System.Collections.Generic.IList TaskOverrides + { + get + { + return ((DataFetcherWithRelations)m_dataparent).GetRelatedObjects("TaskOverrideTask", this); + } + } + #endregion } diff --git a/Duplicati/GUI/Datamodel/TaskExtension.cs b/Duplicati/GUI/Datamodel/TaskExtension.cs new file mode 100644 index 000000000..0df11d696 --- /dev/null +++ b/Duplicati/GUI/Datamodel/TaskExtension.cs @@ -0,0 +1,92 @@ +#region Disclaimer / License +// Copyright (C) 2009, Kenneth Skovhede +// http://www.hexad.dk, opensource@hexad.dk +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +#endregion +/// +/// This class was created by DataClassFileBuilder (LightDatamodel) +/// +/// Table +/// Duplicati.Datamodel +/// TaskExtension +/// +/// + +using System.Data.LightDatamodel; +using System.Data.LightDatamodel.DataClassAttributes; + +namespace Duplicati.Datamodel +{ + + [DatabaseTable("TaskExtension")] + public partial class TaskExtension : DataClassBase + { + +#region " private members " + + [AutoIncrement, PrimaryKey, DatabaseField("ID")] + private System.Int64 m_ID = long.MinValue; + [Relation("TaskExtensionTask", typeof(Task), "ID"), DatabaseField("TaskID")] + private System.Int64 m_TaskID = long.MinValue; + [DatabaseField("Name")] + private System.String m_Name = ""; + [DatabaseField("Value")] + private System.String m_Value = ""; +#endregion + +#region " properties " + + public System.Int64 ID + { + get{return m_ID;} + set{object oldvalue = m_ID;OnBeforeDataChange(this, "ID", oldvalue, value);m_ID = value;OnAfterDataChange(this, "ID", oldvalue, value);} + } + + public System.Int64 TaskID + { + get{return m_TaskID;} + set{object oldvalue = m_TaskID;OnBeforeDataChange(this, "TaskID", oldvalue, value);m_TaskID = value;OnAfterDataChange(this, "TaskID", oldvalue, value);} + } + + public System.String Name + { + get{return m_Name;} + set{object oldvalue = m_Name;OnBeforeDataChange(this, "Name", oldvalue, value);m_Name = value;OnAfterDataChange(this, "Name", oldvalue, value);} + } + + public System.String Value + { + get{return m_Value;} + set{object oldvalue = m_Value;OnBeforeDataChange(this, "Value", oldvalue, value);m_Value = value;OnAfterDataChange(this, "Value", oldvalue, value);} + } + +#endregion + +#region " referenced properties " + + [Affects(typeof(Task))] + public Task Task + { + get{ return ((DataFetcherWithRelations)m_dataparent).GetRelatedObject("TaskExtensionTask", this); } + set{ ((DataFetcherWithRelations)m_dataparent).SetRelatedObject("TaskExtensionTask", this, value); } + } + +#endregion + + } + +} \ No newline at end of file diff --git a/Duplicati/GUI/Datamodel/TaskSetting.cs b/Duplicati/GUI/Datamodel/TaskOverride.cs similarity index 90% rename from Duplicati/GUI/Datamodel/TaskSetting.cs rename to Duplicati/GUI/Datamodel/TaskOverride.cs index d86cee0fb..0669d9b1d 100644 --- a/Duplicati/GUI/Datamodel/TaskSetting.cs +++ b/Duplicati/GUI/Datamodel/TaskOverride.cs @@ -22,7 +22,7 @@ /// /// Table /// Duplicati.Datamodel -/// TaskSetting +/// TaskOverride /// /// @@ -32,15 +32,15 @@ using System.Data.LightDatamodel.DataClassAttributes; namespace Duplicati.Datamodel { - [DatabaseTable("TaskSetting")] - public partial class TaskSetting : DataClassBase + [DatabaseTable("TaskOverride")] + public partial class TaskOverride : DataClassBase { #region " private members " [AutoIncrement, PrimaryKey, DatabaseField("ID")] private System.Int64 m_ID = long.MinValue; - [Relation("TaskSettingTask", typeof(Task), "ID"), DatabaseField("TaskID")] + [Relation("TaskOverrideTask", typeof(Task), "ID"), DatabaseField("TaskID")] private System.Int64 m_TaskID = long.MinValue; [DatabaseField("Name")] private System.String m_Name = ""; @@ -81,8 +81,8 @@ namespace Duplicati.Datamodel [Affects(typeof(Task))] public Task Task { - get{ return ((DataFetcherWithRelations)m_dataparent).GetRelatedObject("TaskSettingTask", this); } - set{ ((DataFetcherWithRelations)m_dataparent).SetRelatedObject("TaskSettingTask", this, value); } + get{ return ((DataFetcherWithRelations)m_dataparent).GetRelatedObject("TaskOverrideTask", this); } + set{ ((DataFetcherWithRelations)m_dataparent).SetRelatedObject("TaskOverrideTask", this, value); } } #endregion diff --git a/Duplicati/GUI/Duplicati.csproj b/Duplicati/GUI/Duplicati.csproj index b0892966f..03cbcee59 100644 --- a/Duplicati/GUI/Duplicati.csproj +++ b/Duplicati/GUI/Duplicati.csproj @@ -195,6 +195,18 @@ FinishedAdd.cs + + UserControl + + + GeneratedFilenameOptions.cs + + + UserControl + + + SettingOverrides.cs + UserControl @@ -590,6 +602,17 @@ + + + + Designer + GeneratedFilenameOptions.cs + + + Designer + SettingOverrides.cs + + diff --git a/Duplicati/GUI/Service controls/Backends/FileSettings.Designer.cs b/Duplicati/GUI/Service controls/Backends/FileSettings.Designer.cs index eaebe7255..3c4fb652a 100644 --- a/Duplicati/GUI/Service controls/Backends/FileSettings.Designer.cs +++ b/Duplicati/GUI/Service controls/Backends/FileSettings.Designer.cs @@ -48,13 +48,9 @@ namespace Duplicati.GUI.Service_controls private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); - this.panel1 = new System.Windows.Forms.Panel(); - this.TimeSeperator = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); this.BrowseTargetFolder = new System.Windows.Forms.Button(); this.DestinationFolder = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); - this.panel1.SuspendLayout(); this.SuspendLayout(); // // button1 @@ -67,32 +63,6 @@ namespace Duplicati.GUI.Service_controls this.button1.Text = "Advanced <<<"; this.button1.UseVisualStyleBackColor = true; // - // panel1 - // - this.panel1.Controls.Add(this.TimeSeperator); - this.panel1.Controls.Add(this.label2); - this.panel1.Location = new System.Drawing.Point(0, 24); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(264, 32); - this.panel1.TabIndex = 3; - // - // TimeSeperator - // - this.TimeSeperator.Location = new System.Drawing.Point(112, 8); - this.TimeSeperator.Name = "TimeSeperator"; - this.TimeSeperator.Size = new System.Drawing.Size(24, 20); - this.TimeSeperator.TabIndex = 2; - this.TimeSeperator.TextChanged += new System.EventHandler(this.TimeSeperator_TextChanged); - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(8, 8); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(77, 13); - this.label2.TabIndex = 0; - this.label2.Text = "Time seperator"; - // // BrowseTargetFolder // this.BrowseTargetFolder.Location = new System.Drawing.Point(240, 0); @@ -125,14 +95,11 @@ namespace Duplicati.GUI.Service_controls this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.BrowseTargetFolder); - this.Controls.Add(this.panel1); this.Controls.Add(this.DestinationFolder); this.Controls.Add(this.button1); this.Controls.Add(this.label1); this.Name = "FileSettings"; this.Size = new System.Drawing.Size(268, 96); - this.panel1.ResumeLayout(false); - this.panel1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -141,9 +108,6 @@ namespace Duplicati.GUI.Service_controls #endregion private System.Windows.Forms.Button button1; - private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.TextBox TimeSeperator; - private System.Windows.Forms.Label label2; private System.Windows.Forms.Button BrowseTargetFolder; private System.Windows.Forms.TextBox DestinationFolder; private System.Windows.Forms.Label label1; diff --git a/Duplicati/GUI/Service controls/Backends/FileSettings.cs b/Duplicati/GUI/Service controls/Backends/FileSettings.cs index 8082cac70..ef799d100 100644 --- a/Duplicati/GUI/Service controls/Backends/FileSettings.cs +++ b/Duplicati/GUI/Service controls/Backends/FileSettings.cs @@ -46,7 +46,6 @@ namespace Duplicati.GUI.Service_controls m_file = file; DestinationFolder.Text = m_file.DestinationFolder; - TimeSeperator.Text = m_file.TimeSeparator; } finally { @@ -62,14 +61,6 @@ namespace Duplicati.GUI.Service_controls m_file.DestinationFolder = DestinationFolder.Text; } - private void TimeSeperator_TextChanged(object sender, EventArgs e) - { - if (m_isUpdating || m_file == null) - return; - - m_file.TimeSeparator = TimeSeperator.Text; - } - private void BrowseTargetFolder_Click(object sender, EventArgs e) { FolderBrowserDialog dlg = new FolderBrowserDialog(); diff --git a/Duplicati/GUI/Service controls/ScheduleSettings.cs b/Duplicati/GUI/Service controls/ScheduleSettings.cs index dc7e26f77..5957336db 100644 --- a/Duplicati/GUI/Service controls/ScheduleSettings.cs +++ b/Duplicati/GUI/Service controls/ScheduleSettings.cs @@ -92,10 +92,10 @@ namespace Duplicati.GUI.Service_controls ForceFullBackup.Checked = !string.IsNullOrEmpty(m_schedule.Task.FullAfter); ForceFullBackupTimespan.Text = m_schedule.Task.FullAfter; - MaxUploaded.Text = m_schedule.Task.MaxUploadsize; - VolumeSize.Text = m_schedule.Task.VolumeSize; - DownloadBandwidth.Text = m_schedule.Task.DownloadBandwidth; - UploadBandwidth.Text =m_schedule.Task.UploadBandwidth; + MaxUploaded.Text = m_schedule.Task.Extensions.MaxUploadSize; + VolumeSize.Text = m_schedule.Task.Extensions.VolumeSize; + DownloadBandwidth.Text = m_schedule.Task.Extensions.DownloadBandwidth; + UploadBandwidth.Text =m_schedule.Task.Extensions.UploadBandwidth; } finally { @@ -234,7 +234,7 @@ namespace Duplicati.GUI.Service_controls try { Library.Core.Sizeparser.ParseSize(MaxUploaded.Text); - m_schedule.Task.MaxUploadsize = MaxUploaded.Text; + m_schedule.Task.Extensions.MaxUploadSize = MaxUploaded.Text; errorProvider.SetError(MaxUploaded, ""); } catch (Exception ex) @@ -251,7 +251,7 @@ namespace Duplicati.GUI.Service_controls try { Library.Core.Sizeparser.ParseSize(VolumeSize.Text); - m_schedule.Task.VolumeSize = VolumeSize.Text; + m_schedule.Task.Extensions.VolumeSize = VolumeSize.Text; errorProvider.SetError(VolumeSize, ""); } catch (Exception ex) @@ -268,7 +268,7 @@ namespace Duplicati.GUI.Service_controls try { Library.Core.Sizeparser.ParseSize(UploadBandwidth.Text); - m_schedule.Task.UploadBandwidth = UploadBandwidth.Text; + m_schedule.Task.Extensions.UploadBandwidth = UploadBandwidth.Text; errorProvider.SetError(UploadBandwidth, ""); } catch (Exception ex) @@ -286,7 +286,7 @@ namespace Duplicati.GUI.Service_controls try { Library.Core.Sizeparser.ParseSize(DownloadBandwidth.Text); - m_schedule.Task.DownloadBandwidth = DownloadBandwidth.Text; + m_schedule.Task.Extensions.DownloadBandwidth = DownloadBandwidth.Text; errorProvider.SetError(DownloadBandwidth, ""); } catch (Exception ex) diff --git a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.Designer.cs b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.Designer.cs index deed32b6a..8517e16a6 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.Designer.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.Designer.cs @@ -33,12 +33,14 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup this.ThrottleOptions = new System.Windows.Forms.CheckBox(); this.EditFilters = new System.Windows.Forms.CheckBox(); this.IncludeDuplicatiSetup = new System.Windows.Forms.CheckBox(); + this.EditVolumeFilenames = new System.Windows.Forms.CheckBox(); + this.EditOverrides = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // // SelectWhen // this.SelectWhen.AutoSize = true; - this.SelectWhen.Location = new System.Drawing.Point(32, 32); + this.SelectWhen.Location = new System.Drawing.Point(32, 8); this.SelectWhen.Name = "SelectWhen"; this.SelectWhen.Size = new System.Drawing.Size(265, 17); this.SelectWhen.TabIndex = 0; @@ -48,7 +50,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup // SelectIncremental // this.SelectIncremental.AutoSize = true; - this.SelectIncremental.Location = new System.Drawing.Point(32, 64); + this.SelectIncremental.Location = new System.Drawing.Point(32, 40); this.SelectIncremental.Name = "SelectIncremental"; this.SelectIncremental.Size = new System.Drawing.Size(439, 17); this.SelectIncremental.TabIndex = 1; @@ -59,7 +61,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup // ThrottleOptions // this.ThrottleOptions.AutoSize = true; - this.ThrottleOptions.Location = new System.Drawing.Point(32, 96); + this.ThrottleOptions.Location = new System.Drawing.Point(32, 72); this.ThrottleOptions.Name = "ThrottleOptions"; this.ThrottleOptions.Size = new System.Drawing.Size(329, 17); this.ThrottleOptions.TabIndex = 3; @@ -69,7 +71,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup // EditFilters // this.EditFilters.AutoSize = true; - this.EditFilters.Location = new System.Drawing.Point(32, 128); + this.EditFilters.Location = new System.Drawing.Point(32, 104); this.EditFilters.Name = "EditFilters"; this.EditFilters.Size = new System.Drawing.Size(316, 17); this.EditFilters.TabIndex = 4; @@ -81,17 +83,39 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup this.IncludeDuplicatiSetup.AutoSize = true; this.IncludeDuplicatiSetup.Checked = true; this.IncludeDuplicatiSetup.CheckState = System.Windows.Forms.CheckState.Checked; - this.IncludeDuplicatiSetup.Location = new System.Drawing.Point(32, 160); + this.IncludeDuplicatiSetup.Location = new System.Drawing.Point(32, 200); this.IncludeDuplicatiSetup.Name = "IncludeDuplicatiSetup"; this.IncludeDuplicatiSetup.Size = new System.Drawing.Size(256, 17); this.IncludeDuplicatiSetup.TabIndex = 5; this.IncludeDuplicatiSetup.Text = "Include the current Duplicati setup in the backup"; this.IncludeDuplicatiSetup.UseVisualStyleBackColor = true; // + // EditVolumeFilenames + // + this.EditVolumeFilenames.AutoSize = true; + this.EditVolumeFilenames.Location = new System.Drawing.Point(32, 136); + this.EditVolumeFilenames.Name = "EditVolumeFilenames"; + this.EditVolumeFilenames.Size = new System.Drawing.Size(369, 17); + this.EditVolumeFilenames.TabIndex = 6; + this.EditVolumeFilenames.Text = "Change the generated names for files stored on the backend (advanced)"; + this.EditVolumeFilenames.UseVisualStyleBackColor = true; + // + // EditOverrides + // + this.EditOverrides.AutoSize = true; + this.EditOverrides.Location = new System.Drawing.Point(32, 168); + this.EditOverrides.Name = "EditOverrides"; + this.EditOverrides.Size = new System.Drawing.Size(228, 17); + this.EditOverrides.TabIndex = 7; + this.EditOverrides.Text = "Manually override settings (very advanced)"; + this.EditOverrides.UseVisualStyleBackColor = true; + // // AdvancedOptions // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.EditOverrides); + this.Controls.Add(this.EditVolumeFilenames); this.Controls.Add(this.IncludeDuplicatiSetup); this.Controls.Add(this.EditFilters); this.Controls.Add(this.ThrottleOptions); @@ -111,5 +135,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup private System.Windows.Forms.CheckBox ThrottleOptions; private System.Windows.Forms.CheckBox EditFilters; private System.Windows.Forms.CheckBox IncludeDuplicatiSetup; + private System.Windows.Forms.CheckBox EditVolumeFilenames; + private System.Windows.Forms.CheckBox EditOverrides; } } diff --git a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.cs b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.cs index 4aed65ff2..0fb8aefcf 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.cs @@ -45,7 +45,10 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup { m_wrapper = new WizardSettingsWrapper(m_settings); if (!m_valuesAutoLoaded) + { IncludeDuplicatiSetup.Checked = m_wrapper.IncludeSetup; + EditOverrides.Checked = m_wrapper.Overrides.Count > 0; + } } void AdvancedOptions_PageLeave(object sender, PageChangedArgs args) @@ -54,6 +57,8 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup m_settings["Advanced:Incremental"] = SelectIncremental.Checked; m_settings["Advanced:Throttle"] = ThrottleOptions.Checked; m_settings["Advanced:Filters"] = EditFilters.Checked; + m_settings["Advanced:Filenames"] = EditVolumeFilenames.Checked; + m_settings["Advanced:Overrides"] = EditOverrides.Checked; if (args.Direction == PageChangedDirection.Back) return; @@ -68,6 +73,10 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup args.NextPage = new Wizard_pages.Add_backup.ThrottleOptions(); else if (EditFilters.Checked) args.NextPage = new Wizard_pages.Add_backup.EditFilters(); + else if (EditVolumeFilenames.Checked) + args.NextPage = new Wizard_pages.Add_backup.GeneratedFilenameOptions(); + else if (EditOverrides.Checked) + args.NextPage = new Wizard_pages.Add_backup.SettingOverrides(); else args.NextPage = new Wizard_pages.Add_backup.FinishedAdd(); } diff --git a/Duplicati/GUI/Wizard pages/Add backup/EditFilters.cs b/Duplicati/GUI/Wizard pages/Add backup/EditFilters.cs index 44cf4e5d4..d83fd3057 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/EditFilters.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/EditFilters.cs @@ -48,7 +48,12 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup m_wrapper.EncodedFilters = filterEditor1.Filter; - args.NextPage = new Wizard_pages.Add_backup.FinishedAdd(); + if ((bool)m_settings["Advanced:Filenames"]) + args.NextPage = new Wizard_pages.Add_backup.GeneratedFilenameOptions(); + else if ((bool)m_settings["Advanced:Overrides"]) + args.NextPage = new Wizard_pages.Add_backup.SettingOverrides(); + else + args.NextPage = new Wizard_pages.Add_backup.FinishedAdd(); } void FilterEditor_PageEnter(object sender, System.Windows.Forms.Wizard.PageChangedArgs args) diff --git a/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.Designer.cs b/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.Designer.cs new file mode 100644 index 000000000..9375177e4 --- /dev/null +++ b/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.Designer.cs @@ -0,0 +1,111 @@ +namespace Duplicati.GUI.Wizard_pages.Add_backup +{ + partial class GeneratedFilenameOptions + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.FilePrefixEnabled = new System.Windows.Forms.CheckBox(); + this.UseShortFilenames = new System.Windows.Forms.CheckBox(); + this.FilePrefix = new System.Windows.Forms.TextBox(); + this.FileTimeSeperator = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(40, 24); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(92, 13); + this.label1.TabIndex = 0; + this.label1.Text = "File time seperator"; + // + // FilePrefixEnabled + // + this.FilePrefixEnabled.AutoSize = true; + this.FilePrefixEnabled.Location = new System.Drawing.Point(24, 56); + this.FilePrefixEnabled.Name = "FilePrefixEnabled"; + this.FilePrefixEnabled.Size = new System.Drawing.Size(133, 17); + this.FilePrefixEnabled.TabIndex = 1; + this.FilePrefixEnabled.Text = "Change filename prefix"; + this.FilePrefixEnabled.UseVisualStyleBackColor = true; + this.FilePrefixEnabled.CheckedChanged += new System.EventHandler(this.FilePrefixEnabled_CheckedChanged); + // + // UseShortFilenames + // + this.UseShortFilenames.AutoSize = true; + this.UseShortFilenames.Location = new System.Drawing.Point(24, 88); + this.UseShortFilenames.Name = "UseShortFilenames"; + this.UseShortFilenames.Size = new System.Drawing.Size(118, 17); + this.UseShortFilenames.TabIndex = 2; + this.UseShortFilenames.Text = "Use short filenames"; + this.UseShortFilenames.UseVisualStyleBackColor = true; + // + // FilePrefix + // + this.FilePrefix.Enabled = false; + this.FilePrefix.Location = new System.Drawing.Point(168, 56); + this.FilePrefix.Name = "FilePrefix"; + this.FilePrefix.Size = new System.Drawing.Size(128, 20); + this.FilePrefix.TabIndex = 3; + // + // FileTimeSeperator + // + this.FileTimeSeperator.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.FileTimeSeperator.FormattingEnabled = true; + this.FileTimeSeperator.Items.AddRange(new object[] { + "\'", + ":", + "_"}); + this.FileTimeSeperator.Location = new System.Drawing.Point(168, 24); + this.FileTimeSeperator.Name = "FileTimeSeperator"; + this.FileTimeSeperator.Size = new System.Drawing.Size(56, 22); + this.FileTimeSeperator.TabIndex = 4; + // + // GeneratedFilenameOptions + // + this.Controls.Add(this.FileTimeSeperator); + this.Controls.Add(this.FilePrefix); + this.Controls.Add(this.UseShortFilenames); + this.Controls.Add(this.FilePrefixEnabled); + this.Controls.Add(this.label1); + this.Name = "GeneratedFilenameOptions"; + this.Size = new System.Drawing.Size(506, 242); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.CheckBox FilePrefixEnabled; + private System.Windows.Forms.CheckBox UseShortFilenames; + private System.Windows.Forms.TextBox FilePrefix; + private System.Windows.Forms.ComboBox FileTimeSeperator; + } +} diff --git a/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.cs b/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.cs new file mode 100644 index 000000000..8fdf5f5a1 --- /dev/null +++ b/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.cs @@ -0,0 +1,79 @@ +#region Disclaimer / License +// Copyright (C) 2009, Kenneth Skovhede +// http://www.hexad.dk, opensource@hexad.dk +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +#endregion +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace Duplicati.GUI.Wizard_pages.Add_backup +{ + public partial class GeneratedFilenameOptions : System.Windows.Forms.Wizard.WizardControl + { + private WizardSettingsWrapper m_wrapper; + + public GeneratedFilenameOptions() + : base("Generated filenames", "On this page you can control how filenames are generated. This can be used if the remote server does not support the default filenames.") + { + InitializeComponent(); + + base.PageEnter += new System.Windows.Forms.Wizard.PageChangeHandler(GeneratedFilenameOptions_PageEnter); + base.PageLeave += new System.Windows.Forms.Wizard.PageChangeHandler(GeneratedFilenameOptions_PageLeave); + } + + void GeneratedFilenameOptions_PageLeave(object sender, System.Windows.Forms.Wizard.PageChangedArgs args) + { + if (args.Direction == System.Windows.Forms.Wizard.PageChangedDirection.Back) + return; + + m_wrapper.FileTimeSeperator = FileTimeSeperator.Text; + m_wrapper.FilePrefix = FilePrefixEnabled.Checked ? "" : FilePrefix.Text; + m_wrapper.ShortFilenames = UseShortFilenames.Checked; + + if ((bool)m_settings["Advanced:Overrides"]) + args.NextPage = new Wizard_pages.Add_backup.SettingOverrides(); + else + args.NextPage = new Wizard_pages.Add_backup.FinishedAdd(); + + } + + void GeneratedFilenameOptions_PageEnter(object sender, System.Windows.Forms.Wizard.PageChangedArgs args) + { + m_wrapper = new WizardSettingsWrapper(m_settings); + if (!m_valuesAutoLoaded) + { + FileTimeSeperator.Text = m_wrapper.FileTimeSeperator; + if (FileTimeSeperator.Text == "") + FileTimeSeperator.Text = ":"; + FilePrefixEnabled.Checked = !string.IsNullOrEmpty(m_wrapper.FilePrefix); + FilePrefix.Text = m_wrapper.FilePrefix; + UseShortFilenames.Checked = m_wrapper.ShortFilenames; + } + } + + private void FilePrefixEnabled_CheckedChanged(object sender, EventArgs e) + { + FilePrefix.Enabled = FilePrefixEnabled.Checked; + } + } +} + diff --git a/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.resx b/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.resx new file mode 100644 index 000000000..ff31a6db5 --- /dev/null +++ b/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Duplicati/GUI/Wizard pages/Add backup/IncrementalSettings.cs b/Duplicati/GUI/Wizard pages/Add backup/IncrementalSettings.cs index 16aa534c3..0f073805d 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/IncrementalSettings.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/IncrementalSettings.cs @@ -131,6 +131,10 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup args.NextPage = new Wizard_pages.Add_backup.ThrottleOptions(); else if ((bool)m_settings["Advanced:Filters"]) args.NextPage = new Wizard_pages.Add_backup.EditFilters(); + else if ((bool)m_settings["Advanced:Filenames"]) + args.NextPage = new Wizard_pages.Add_backup.GeneratedFilenameOptions(); + else if ((bool)m_settings["Advanced:Overrides"]) + args.NextPage = new Wizard_pages.Add_backup.SettingOverrides(); else args.NextPage = new Wizard_pages.Add_backup.FinishedAdd(); } diff --git a/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs b/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs index aaaeec4fc..640e7eeed 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs @@ -89,7 +89,9 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup m_owner.Cancelled -= new CancelEventHandler(m_owner_Cancelled); m_settings["Files:Sizes"] = m_sizes; m_settings["Files:WarnedFilters"] = m_warnedFiltersChanged; - m_calculator.ClearQueue(true); + + if (m_calculator != null) + m_calculator.ClearQueue(true); if (args.Direction == PageChangedDirection.Back) return; diff --git a/Duplicati/GUI/Wizard pages/Add backup/SelectWhen.cs b/Duplicati/GUI/Wizard pages/Add backup/SelectWhen.cs index c1988861f..98cd5c318 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/SelectWhen.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/SelectWhen.cs @@ -105,6 +105,10 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup args.NextPage = new Wizard_pages.Add_backup.ThrottleOptions(); else if ((bool)m_settings["Advanced:Filters"]) args.NextPage = new Wizard_pages.Add_backup.EditFilters(); + else if ((bool)m_settings["Advanced:Filenames"]) + args.NextPage = new Wizard_pages.Add_backup.GeneratedFilenameOptions(); + else if ((bool)m_settings["Advanced:Overrides"]) + args.NextPage = new Wizard_pages.Add_backup.SettingOverrides(); else args.NextPage = new Wizard_pages.Add_backup.FinishedAdd(); } diff --git a/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.Designer.cs b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.Designer.cs new file mode 100644 index 000000000..eb3abc8c5 --- /dev/null +++ b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.Designer.cs @@ -0,0 +1,183 @@ +namespace Duplicati.GUI.Wizard_pages.Add_backup +{ + partial class SettingOverrides + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.OptionsGrid = new System.Windows.Forms.DataGridView(); + this.InfoLabel = new System.Windows.Forms.Label(); + this.BaseDataSet = new System.Data.DataSet(); + this.OverrideTable = new System.Data.DataTable(); + this.EnabledDataColumn = new System.Data.DataColumn(); + this.NameDataColumn = new System.Data.DataColumn(); + this.ValueDataColumn = new System.Data.DataColumn(); + this.enabledDataGridViewCheckBoxColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn(); + this.nameDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.valueDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.argumentDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.argumentDataColumn = new System.Data.DataColumn(); + ((System.ComponentModel.ISupportInitialize)(this.OptionsGrid)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.BaseDataSet)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.OverrideTable)).BeginInit(); + this.SuspendLayout(); + // + // OptionsGrid + // + this.OptionsGrid.AllowUserToAddRows = false; + this.OptionsGrid.AllowUserToDeleteRows = false; + this.OptionsGrid.AutoGenerateColumns = false; + this.OptionsGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.OptionsGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.enabledDataGridViewCheckBoxColumn, + this.nameDataGridViewTextBoxColumn, + this.valueDataGridViewTextBoxColumn, + this.argumentDataGridViewTextBoxColumn}); + this.OptionsGrid.DataMember = "OverrideTable"; + this.OptionsGrid.DataSource = this.BaseDataSet; + this.OptionsGrid.Location = new System.Drawing.Point(16, 16); + this.OptionsGrid.MultiSelect = false; + this.OptionsGrid.Name = "OptionsGrid"; + this.OptionsGrid.RowHeadersVisible = false; + this.OptionsGrid.Size = new System.Drawing.Size(472, 144); + this.OptionsGrid.TabIndex = 0; + this.OptionsGrid.RowEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.OptionsGrid_RowEnter); + this.OptionsGrid.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.OptionsGrid_CellEndEdit); + // + // InfoLabel + // + this.InfoLabel.Location = new System.Drawing.Point(16, 168); + this.InfoLabel.Name = "InfoLabel"; + this.InfoLabel.Size = new System.Drawing.Size(472, 64); + this.InfoLabel.TabIndex = 0; + this.InfoLabel.Text = "Description panel"; + // + // BaseDataSet + // + this.BaseDataSet.DataSetName = "BaseDataSet"; + this.BaseDataSet.Tables.AddRange(new System.Data.DataTable[] { + this.OverrideTable}); + // + // OverrideTable + // + this.OverrideTable.Columns.AddRange(new System.Data.DataColumn[] { + this.EnabledDataColumn, + this.NameDataColumn, + this.ValueDataColumn, + this.argumentDataColumn}); + this.OverrideTable.TableName = "OverrideTable"; + // + // EnabledDataColumn + // + this.EnabledDataColumn.Caption = "Enabled"; + this.EnabledDataColumn.ColumnName = "Enabled"; + this.EnabledDataColumn.DataType = typeof(bool); + // + // NameDataColumn + // + this.NameDataColumn.Caption = "Name"; + this.NameDataColumn.ColumnName = "Name"; + // + // ValueDataColumn + // + this.ValueDataColumn.Caption = "Value"; + this.ValueDataColumn.ColumnName = "Value"; + // + // enabledDataGridViewCheckBoxColumn + // + this.enabledDataGridViewCheckBoxColumn.DataPropertyName = "Enabled"; + this.enabledDataGridViewCheckBoxColumn.HeaderText = "Enabled"; + this.enabledDataGridViewCheckBoxColumn.Name = "enabledDataGridViewCheckBoxColumn"; + this.enabledDataGridViewCheckBoxColumn.Width = 50; + // + // nameDataGridViewTextBoxColumn + // + this.nameDataGridViewTextBoxColumn.DataPropertyName = "Name"; + this.nameDataGridViewTextBoxColumn.HeaderText = "Name"; + this.nameDataGridViewTextBoxColumn.Name = "nameDataGridViewTextBoxColumn"; + this.nameDataGridViewTextBoxColumn.ReadOnly = true; + this.nameDataGridViewTextBoxColumn.Width = 150; + // + // valueDataGridViewTextBoxColumn + // + this.valueDataGridViewTextBoxColumn.DataPropertyName = "Value"; + this.valueDataGridViewTextBoxColumn.HeaderText = "Value"; + this.valueDataGridViewTextBoxColumn.Name = "valueDataGridViewTextBoxColumn"; + this.valueDataGridViewTextBoxColumn.Width = 240; + // + // dataGridViewTextBoxColumn1 + // + this.dataGridViewTextBoxColumn1.DataPropertyName = "argument"; + this.dataGridViewTextBoxColumn1.HeaderText = "argument"; + this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1"; + this.dataGridViewTextBoxColumn1.Visible = false; + this.dataGridViewTextBoxColumn1.Width = 5; + // + // argumentDataGridViewTextBoxColumn + // + this.argumentDataGridViewTextBoxColumn.DataPropertyName = "argument"; + this.argumentDataGridViewTextBoxColumn.HeaderText = "argument"; + this.argumentDataGridViewTextBoxColumn.Name = "argumentDataGridViewTextBoxColumn"; + this.argumentDataGridViewTextBoxColumn.Visible = false; + this.argumentDataGridViewTextBoxColumn.Width = 5; + // + // argumentDataColumn + // + this.argumentDataColumn.Caption = "argument"; + this.argumentDataColumn.ColumnName = "argument"; + this.argumentDataColumn.DataType = typeof(object); + // + // SettingOverrides + // + this.Controls.Add(this.InfoLabel); + this.Controls.Add(this.OptionsGrid); + this.Name = "SettingOverrides"; + this.Size = new System.Drawing.Size(506, 242); + ((System.ComponentModel.ISupportInitialize)(this.OptionsGrid)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.BaseDataSet)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.OverrideTable)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.DataGridView OptionsGrid; + private System.Windows.Forms.Label InfoLabel; + private System.Data.DataSet BaseDataSet; + private System.Data.DataTable OverrideTable; + private System.Data.DataColumn EnabledDataColumn; + private System.Data.DataColumn NameDataColumn; + private System.Data.DataColumn ValueDataColumn; + private System.Data.DataColumn argumentDataColumn; + private System.Windows.Forms.DataGridViewCheckBoxColumn enabledDataGridViewCheckBoxColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn nameDataGridViewTextBoxColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn valueDataGridViewTextBoxColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn argumentDataGridViewTextBoxColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1; + } +} diff --git a/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs new file mode 100644 index 000000000..78b3e06fd --- /dev/null +++ b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs @@ -0,0 +1,106 @@ +#region Disclaimer / License +// Copyright (C) 2009, Kenneth Skovhede +// http://www.hexad.dk, opensource@hexad.dk +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +#endregion +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace Duplicati.GUI.Wizard_pages.Add_backup +{ + public partial class SettingOverrides : System.Windows.Forms.Wizard.WizardControl + { + private WizardSettingsWrapper m_wrapper; + + public SettingOverrides() + : base("Override settings", "On this page you can override all settings supported by Duplicati. This is very advanced, so be carefull!") + { + InitializeComponent(); + + m_autoFillValues = false; + base.PageEnter += new System.Windows.Forms.Wizard.PageChangeHandler(SettingOverrides_PageEnter); + base.PageLeave += new System.Windows.Forms.Wizard.PageChangeHandler(SettingOverrides_PageLeave); + } + + void SettingOverrides_PageLeave(object sender, System.Windows.Forms.Wizard.PageChangedArgs args) + { + if (args.Direction == System.Windows.Forms.Wizard.PageChangedDirection.Back) + return; + + m_wrapper.Overrides.Clear(); + foreach (DataRow dr in OverrideTable.Rows) + if ((bool)dr["Enabled"]) + m_wrapper.Overrides.Add((string)dr["Name"], (string)dr["Value"]); + + args.NextPage = new Wizard_pages.Add_backup.FinishedAdd(); + } + + void SettingOverrides_PageEnter(object sender, System.Windows.Forms.Wizard.PageChangedArgs args) + { + m_wrapper = new WizardSettingsWrapper(m_settings); + + if (!m_settings.ContainsKey("Overrides:Table")) + { + OverrideTable.Rows.Clear(); + + Library.Main.Options opt = new Library.Main.Options(new Dictionary()); + foreach (Library.Backend.ICommandLineArgument arg in opt.SupportedCommands) + { + DataRow dr = OverrideTable.NewRow(); + dr["Enabled"] = m_wrapper.Overrides.ContainsKey(arg.Name); + dr["argument"] = arg; + dr["Name"] = arg.Name; + if (m_wrapper.Overrides.ContainsKey(arg.Name)) + dr["Value"] = m_wrapper.Overrides[arg.Name]; + OverrideTable.Rows.Add(dr); + } + + m_settings["Overrides:Table"] = BaseDataSet; + } + else + { + BaseDataSet = (DataSet)m_settings["Overrides:Table"]; + OptionsGrid.DataSource = BaseDataSet; + OverrideTable = BaseDataSet.Tables["OverrideTable"]; + OptionsGrid.DataMember = "OverrideTable"; + } + + } + + private void OptionsGrid_RowEnter(object sender, DataGridViewCellEventArgs e) + { + DataRow r = OverrideTable.Rows[e.RowIndex]; + Library.Backend.ICommandLineArgument arg = (Library.Backend.ICommandLineArgument)r["argument"]; + InfoLabel.Text = string.Format("Type: {0}. {1}. {2}", arg.Type.ToString(), arg.ShortDescription, arg.LongDescription); + } + + private void OptionsGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e) + { + if (e.ColumnIndex != 0) + { + DataRow r = OverrideTable.Rows[e.RowIndex]; + r["Enabled"] = r["Value"] != DBNull.Value; + } + } + } +} + diff --git a/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.resx b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.resx new file mode 100644 index 000000000..f39ce09d5 --- /dev/null +++ b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Duplicati/GUI/Wizard pages/Add backup/ThrottleOptions.Designer.cs b/Duplicati/GUI/Wizard pages/Add backup/ThrottleOptions.Designer.cs index 8e856d585..4410f7fde 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/ThrottleOptions.Designer.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/ThrottleOptions.Designer.cs @@ -132,7 +132,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup // BackupLimitEnabled // this.BackupLimitEnabled.AutoSize = true; - this.BackupLimitEnabled.Location = new System.Drawing.Point(32, 96); + this.BackupLimitEnabled.Location = new System.Drawing.Point(32, 89); this.BackupLimitEnabled.Name = "BackupLimitEnabled"; this.BackupLimitEnabled.Size = new System.Drawing.Size(134, 17); this.BackupLimitEnabled.TabIndex = 9; @@ -150,7 +150,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup "kb", "mb", "gb"}); - this.BackupLimitSuffix.Location = new System.Drawing.Point(281, 95); + this.BackupLimitSuffix.Location = new System.Drawing.Point(281, 88); this.BackupLimitSuffix.Name = "BackupLimitSuffix"; this.BackupLimitSuffix.Size = new System.Drawing.Size(72, 21); this.BackupLimitSuffix.TabIndex = 11; @@ -158,7 +158,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup // BackupLimitNumber // this.BackupLimitNumber.Enabled = false; - this.BackupLimitNumber.Location = new System.Drawing.Point(185, 95); + this.BackupLimitNumber.Location = new System.Drawing.Point(185, 88); this.BackupLimitNumber.Maximum = new decimal(new int[] { 10000, 0, @@ -178,14 +178,14 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup "kb", "mb", "gb"}); - this.VolumeSizeLimitSuffix.Location = new System.Drawing.Point(280, 128); + this.VolumeSizeLimitSuffix.Location = new System.Drawing.Point(280, 120); this.VolumeSizeLimitSuffix.Name = "VolumeSizeLimitSuffix"; this.VolumeSizeLimitSuffix.Size = new System.Drawing.Size(72, 21); this.VolumeSizeLimitSuffix.TabIndex = 14; // // VolumeSizeLimitNumber // - this.VolumeSizeLimitNumber.Location = new System.Drawing.Point(184, 128); + this.VolumeSizeLimitNumber.Location = new System.Drawing.Point(184, 120); this.VolumeSizeLimitNumber.Maximum = new decimal(new int[] { 10000, 0, @@ -199,7 +199,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup // AsyncEnabled // this.AsyncEnabled.AutoSize = true; - this.AsyncEnabled.Location = new System.Drawing.Point(32, 168); + this.AsyncEnabled.Location = new System.Drawing.Point(32, 160); this.AsyncEnabled.Name = "AsyncEnabled"; this.AsyncEnabled.Size = new System.Drawing.Size(124, 17); this.AsyncEnabled.TabIndex = 15; @@ -209,7 +209,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(48, 128); + this.label1.Location = new System.Drawing.Point(48, 120); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(103, 13); this.label1.TabIndex = 16; @@ -218,7 +218,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup // ThreadPriorityEnabled // this.ThreadPriorityEnabled.AutoSize = true; - this.ThreadPriorityEnabled.Location = new System.Drawing.Point(32, 200); + this.ThreadPriorityEnabled.Location = new System.Drawing.Point(32, 184); this.ThreadPriorityEnabled.Name = "ThreadPriorityEnabled"; this.ThreadPriorityEnabled.Size = new System.Drawing.Size(108, 17); this.ThreadPriorityEnabled.TabIndex = 17; @@ -237,7 +237,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup "Normal", "Below normal", "Low"}); - this.ThreadPriority.Location = new System.Drawing.Point(184, 200); + this.ThreadPriority.Location = new System.Drawing.Point(184, 184); this.ThreadPriority.Name = "ThreadPriority"; this.ThreadPriority.Size = new System.Drawing.Size(168, 21); this.ThreadPriority.TabIndex = 18; diff --git a/Duplicati/GUI/Wizard pages/Add backup/ThrottleOptions.cs b/Duplicati/GUI/Wizard pages/Add backup/ThrottleOptions.cs index 73dd996fe..cc8dab88c 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/ThrottleOptions.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/ThrottleOptions.cs @@ -143,6 +143,10 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup if ((bool)m_settings["Advanced:Filters"]) args.NextPage = new Wizard_pages.Add_backup.EditFilters(); + else if ((bool)m_settings["Advanced:Filenames"]) + args.NextPage = new Wizard_pages.Add_backup.GeneratedFilenameOptions(); + else if ((bool)m_settings["Advanced:Overrides"]) + args.NextPage = new Wizard_pages.Add_backup.SettingOverrides(); else args.NextPage = new FinishedAdd(); } diff --git a/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs b/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs index 110e2dbed..439a495f2 100644 --- a/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs +++ b/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs @@ -131,15 +131,24 @@ namespace Duplicati.GUI.Wizard_pages this.FullBackupInterval = schedule.Task.FullAfter; this.MaxFullBackups = (int)schedule.Task.KeepFull; this.BackupExpireInterval = schedule.Task.KeepTime; - this.UploadSpeedLimit = schedule.Task.UploadBandwidth; - this.DownloadSpeedLimit = schedule.Task.DownloadBandwidth; - this.BackupSizeLimit = schedule.Task.MaxUploadsize; - this.VolumeSize = schedule.Task.VolumeSize; - this.ThreadPriority = schedule.Task.ThreadPriority; - this.AsyncTransfer = schedule.Task.AsyncTransfer; + this.UploadSpeedLimit = schedule.Task.Extensions.UploadBandwidth; + this.DownloadSpeedLimit = schedule.Task.Extensions.DownloadBandwidth; + this.BackupSizeLimit = schedule.Task.Extensions.MaxUploadSize; + this.VolumeSize = schedule.Task.Extensions.VolumeSize; + this.ThreadPriority = schedule.Task.Extensions.ThreadPriority; + this.AsyncTransfer = schedule.Task.Extensions.AsyncTransfer; this.GPGEncryption = schedule.Task.GPGEncryption; this.IncludeSetup = schedule.Task.IncludeSetup; - this.IgnoreFileTimestamps = schedule.Task.IgnoreTimestamps; + this.IgnoreFileTimestamps = schedule.Task.Extensions.IgnoreTimestamps; + this.FileSizeLimit = schedule.Task.Extensions.FileSizeLimit; + + this.FilePrefix = schedule.Task.Extensions.FilenamePrefix; + this.FileTimeSeperator = schedule.Task.Extensions.FileTimeSeperator; + this.ShortFilenames = schedule.Task.Extensions.ShortFilenames; + + this.Overrides = new Dictionary(); + foreach (Datamodel.TaskOverride ov in schedule.Task.TaskOverrides) + this.Overrides[ov.Name] = ov.Value; this.PrimayAction = action; } @@ -156,7 +165,6 @@ namespace Duplicati.GUI.Wizard_pages if (schedule.Task == null) schedule.Task = schedule.DataParent.Add(); schedule.Task.SourcePath = this.SourcePath; - //TODO: This does not correctly erase the old filters? schedule.Task.EncodedFilter = this.EncodedFilters; schedule.Task.Encryptionkey = this.BackupPassword; @@ -227,17 +235,44 @@ namespace Duplicati.GUI.Wizard_pages schedule.Task.KeepFull = this.MaxFullBackups; schedule.Task.KeepTime = this.BackupExpireInterval; - schedule.Task.UploadBandwidth = this.UploadSpeedLimit; - schedule.Task.DownloadBandwidth = this.DownloadSpeedLimit; - schedule.Task.MaxUploadsize = this.BackupSizeLimit; + schedule.Task.Extensions.UploadBandwidth = this.UploadSpeedLimit; + schedule.Task.Extensions.DownloadBandwidth = this.DownloadSpeedLimit; + schedule.Task.Extensions.MaxUploadSize = this.BackupSizeLimit; - schedule.Task.VolumeSize = this.VolumeSize; - schedule.Task.ThreadPriority = this.ThreadPriority; - schedule.Task.AsyncTransfer = this.AsyncTransfer; + schedule.Task.Extensions.VolumeSize = this.VolumeSize; + schedule.Task.Extensions.ThreadPriority = this.ThreadPriority; + schedule.Task.Extensions.AsyncTransfer = this.AsyncTransfer; schedule.Task.GPGEncryption = this.GPGEncryption; schedule.Task.IncludeSetup = this.IncludeSetup; - schedule.Task.IgnoreTimestamps = this.IgnoreFileTimestamps; + schedule.Task.Extensions.IgnoreTimestamps = this.IgnoreFileTimestamps; + schedule.Task.Extensions.FileSizeLimit = this.FileSizeLimit; + + schedule.Task.Extensions.FilenamePrefix = this.FilePrefix; + schedule.Task.Extensions.FileTimeSeperator = this.FileTimeSeperator; + schedule.Task.Extensions.ShortFilenames = this.ShortFilenames; + + //Synchronize the override collections, preserve existing items + Dictionary ovs = new Dictionary(); + foreach (Datamodel.TaskOverride ov in schedule.Task.TaskOverrides) + ovs[ov.Name] = ov; + + foreach (string s in this.Overrides.Keys) + if (ovs.ContainsKey(s)) + { + ovs[s].Value = this.Overrides[s]; + ovs.Remove(s); + } + else + { + Datamodel.TaskOverride ov = schedule.Task.DataParent.Add(); + ov.Name = s; + ov.Value = this.Overrides[s]; + schedule.Task.TaskOverrides.Add(ov); + } + + foreach (Datamodel.TaskOverride ov in ovs.Values) + ov.DataParent.DeleteObject(ov); } /// @@ -390,7 +425,6 @@ namespace Duplicati.GUI.Wizard_pages set { SetItem("BackupExpireInterval", value); } } - /// /// The interval at which to perform full backups /// @@ -427,6 +461,15 @@ namespace Duplicati.GUI.Wizard_pages set { SetItem("VolumeSize", value); } } + /// + /// The maximum size of files included in the backup + /// + public string FileSizeLimit + { + get { return GetItem("FileSizeLimit", ""); } + set { SetItem("FileSizeLimit", value); } + } + /// /// The size of each volume in the backup set /// @@ -544,6 +587,46 @@ namespace Duplicati.GUI.Wizard_pages set { SetItem("IgnoreFileTimestamps", value); } } + /// + /// A prefix to the volume filename + /// + public string FilePrefix + { + get { return GetItem("FilePrefix", ""); } + set { SetItem("FilePrefix", value); } + } + + /// + /// The character used to seperate time digits in the filename + /// + public string FileTimeSeperator + { + get { return GetItem("FileTimeSeperator", ":"); } + set { SetItem("FileTimeSeperator", value); } + } + + /// + /// True if the filenames generated should be short + /// + public bool ShortFilenames + { + get { return GetItem("ShortFilenames", false); } + set { SetItem("ShortFilenames", value); } + } + + /// + /// Gets all the overrides present on the task + /// + public Dictionary Overrides + { + get + { + if (GetItem>("Overrides", null) == null) + this.Overrides = new Dictionary(); + return GetItem>("Overrides", null); + } + set { SetItem("Overrides", value); } + } } /// diff --git a/Duplicati/GUI/WizardHandler.cs b/Duplicati/GUI/WizardHandler.cs index 471830795..5147de7df 100644 --- a/Duplicati/GUI/WizardHandler.cs +++ b/Duplicati/GUI/WizardHandler.cs @@ -117,12 +117,7 @@ namespace Duplicati.GUI { Schedule schedule = Program.DataConnection.GetObjectById(wrapper.ScheduleID); List items = new List(); - items.Add(schedule); - items.Add(schedule.Task); - foreach(TaskSetting ts in schedule.Task.TaskSettings) - items.Add(ts); - foreach (TaskFilter tf in schedule.Task.Filters) - items.Add(tf); + items.AddRange(Program.DataConnection.FindObjectRelations(schedule)); foreach(IDataClass o in items) Program.DataConnection.DeleteObject(o); Program.DataConnection.Commit(items.ToArray()); diff --git a/Duplicati/Library/Backend/File/FileBackend.cs b/Duplicati/Library/Backend/File/FileBackend.cs index f809642ad..168bded16 100644 --- a/Duplicati/Library/Backend/File/FileBackend.cs +++ b/Duplicati/Library/Backend/File/FileBackend.cs @@ -96,7 +96,7 @@ namespace Duplicati.Library.Backend foreach (string s in System.IO.Directory.GetDirectories(path)) { System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(s); - FileEntry fe = new FileEntry(di.Name,0, di.LastAccessTime, di.LastWriteTime); + FileEntry fe = new FileEntry(di.Name, 0, di.LastAccessTime, di.LastWriteTime); fe.IsFolder = true; ls.Add(fe); } diff --git a/Duplicati/Library/Backend/S3/S3Backend.cs b/Duplicati/Library/Backend/S3/S3Backend.cs index c7299f2a4..3fd71712e 100644 --- a/Duplicati/Library/Backend/S3/S3Backend.cs +++ b/Duplicati/Library/Backend/S3/S3Backend.cs @@ -115,7 +115,9 @@ namespace Duplicati.Library.Backend m_bucket = m_host.Substring(0, m_host.Length - ".s3.amazonaws.com".Length); m_host = "s3.amazonaws.com"; m_prefix = u.PathAndQuery; - + + if (m_prefix.StartsWith("/")) + m_prefix = m_prefix.Substring(1); } else throw new Exception("Unable to determine the bucket name for host: " + m_url); @@ -155,7 +157,13 @@ namespace Duplicati.Library.Backend List lst = con.ListBucket(m_bucket, m_prefix); for (int i = 0; i < lst.Count; i++) + { lst[i].Name = lst[i].Name.Substring(m_prefix.Length); + + //Fix for a bug in Duplicati 1.0 beta 3 and earlier, where filenames are incorrectly prefixed with a slash + if (lst[i].Name.StartsWith("/") && !m_prefix.StartsWith("/")) + lst[i].Name = lst[i].Name.Substring(1); + } return lst; } catch (System.Net.WebException wex) diff --git a/Duplicati/Library/Core/Utility.cs b/Duplicati/Library/Core/Utility.cs index d79bd3372..20755ee09 100644 --- a/Duplicati/Library/Core/Utility.cs +++ b/Duplicati/Library/Core/Utility.cs @@ -390,5 +390,34 @@ namespace Duplicati.Library.Core return System.Threading.ThreadPriority.Normal; } } + + /// + /// Parses a string into a boolean value + /// + /// The value to parse + /// The default value, in case the string is not a valid boolean value + /// The parsed value or the default value + public static bool ParseBool(string value, bool @default) + { + if (value == null) + value = ""; + + switch (value.Trim().ToLower()) + { + case "1": + case "on": + case "true": + case "yes": + return true; + case "0": + case "off": + case "false": + case "no": + return false; + default: + return @default; + } + } + } } diff --git a/Duplicati/Library/Main/FilenameStrategy.cs b/Duplicati/Library/Main/FilenameStrategy.cs index 4c0f6a236..b5d8b2fc0 100644 --- a/Duplicati/Library/Main/FilenameStrategy.cs +++ b/Duplicati/Library/Main/FilenameStrategy.cs @@ -101,6 +101,8 @@ namespace Duplicati.Library.Main m = m_shortRegExp.Match(fe.Name); if (!m.Success) return null; + if (m.Value != fe.Name) + return null; //Accept only full matches BackupEntry.EntryType type; if (m.Groups["type"].Value == "manifest" || m.Groups["type"].Value == "M") diff --git a/Duplicati/Library/Main/Interface.cs b/Duplicati/Library/Main/Interface.cs index 02102d9ad..dc1294f26 100644 --- a/Duplicati/Library/Main/Interface.cs +++ b/Duplicati/Library/Main/Interface.cs @@ -82,8 +82,6 @@ namespace Duplicati.Library.Main OperationProgress(this, DuplicatiOperation.Backup, -1, -1, "Loading remote filelist", ""); - FilenameStrategy fns = new FilenameStrategy(m_options); - bool full = m_options.Full; backend = new BackendWrapper(bs, m_backend, m_options); @@ -127,7 +125,7 @@ namespace Duplicati.Library.Main dir.ProgressEvent += new Duplicati.Library.Main.RSync.RSyncDir.ProgressEventDelegate(BackupRSyncDir_ProgressEvent); dir.DisableFiletimeCheck = m_options.DisableFiletimeCheck; - dir.MaxFileSize = m_options.MaxFileSize; + dir.MaxFileSize = m_options.SkipFilesLargerThan; using (new Logging.Timer("Initiating multipass")) dir.InitiateMultiPassDiff(full); diff --git a/Duplicati/Library/Main/Options.cs b/Duplicati/Library/Main/Options.cs index 29853866b..21deaa454 100644 --- a/Duplicati/Library/Main/Options.cs +++ b/Duplicati/Library/Main/Options.cs @@ -119,14 +119,14 @@ namespace Duplicati.Library.Main /// /// Gets the maximum size of a single file /// - public long MaxFileSize + public long SkipFilesLargerThan { get { - if (!m_options.ContainsKey("totalsize") || string.IsNullOrEmpty(m_options["totalsize"])) + if (!m_options.ContainsKey("skip-files-larger-than") || string.IsNullOrEmpty(m_options["skip-files-larger-than"])) return long.MaxValue; else - return Math.Max(VolumeSize, Core.Sizeparser.ParseSize(m_options["totalsize"], "mb")); + return Core.Sizeparser.ParseSize(m_options["skip-files-larger-than"], "mb"); } } diff --git a/thirdparty/LightDataModel/DataClassFileBuilder.exe b/thirdparty/LightDataModel/DataClassFileBuilder.exe index 919799ee3..7b53cb623 100644 Binary files a/thirdparty/LightDataModel/DataClassFileBuilder.exe and b/thirdparty/LightDataModel/DataClassFileBuilder.exe differ diff --git a/thirdparty/LightDataModel/LightDatamodel.dll b/thirdparty/LightDataModel/LightDatamodel.dll index 04157b111..8d2014172 100644 Binary files a/thirdparty/LightDataModel/LightDatamodel.dll and b/thirdparty/LightDataModel/LightDatamodel.dll differ