From 1030577a8e3c5b23637e052d4768b48b51653192 Mon Sep 17 00:00:00 2001 From: "kenneth.skovhede@gmail.com" Date: Wed, 21 Sep 2011 20:13:07 +0000 Subject: [PATCH] Update issue #231 Status: Fixed The globbing expressions are now saved and used. This includes the new filter test dialog that generates globbing rather than regexps. git-svn-id: https://duplicati.googlecode.com/svn/trunk@904 59da171f-624f-0410-aa54-27559c288bec --- .../Database schema/8. Add filter fields.sql | 1 + Duplicati/GUI/Database schema/Schema.sql | 5 +- Duplicati/GUI/Datamodel/Task.Extension.cs | 67 ++- Duplicati/GUI/Datamodel/TaskFilter.cs | 169 +++---- Duplicati/GUI/Duplicati.csproj | 1 + .../HelperControls/FilterDialog.Designer.cs | 2 + Duplicati/GUI/HelperControls/FilterDialog.cs | 93 +++- .../GUI/HelperControls/FilterDialog.resx | 21 +- .../HelperControls/FilterEditor.Designer.cs | 412 +++++++++--------- Duplicati/GUI/HelperControls/FilterEditor.cs | 96 +++- .../GUI/HelperControls/FilterEditor.resx | 74 +++- .../TestSearchSelection.Designer.cs | 6 +- .../GUI/HelperControls/TestSearchSelection.cs | 146 ++++--- .../HelperControls/TestSearchSelection.resx | 226 +++++----- .../Wizard pages/Add backup/EditFilters.cs | 4 +- .../Wizard pages/Add backup/SelectFiles.cs | 21 +- .../GUI/Wizard pages/WizardSettingsWrapper.cs | 10 +- 17 files changed, 819 insertions(+), 535 deletions(-) create mode 100644 Duplicati/GUI/Database schema/8. Add filter fields.sql diff --git a/Duplicati/GUI/Database schema/8. Add filter fields.sql b/Duplicati/GUI/Database schema/8. Add filter fields.sql new file mode 100644 index 000000000..d384b024e --- /dev/null +++ b/Duplicati/GUI/Database schema/8. Add filter fields.sql @@ -0,0 +1 @@ +ALTER TABLE "TaskFilter" ADD COLUMN "GlobbingFilter" TEXT NULL; \ No newline at end of file diff --git a/Duplicati/GUI/Database schema/Schema.sql b/Duplicati/GUI/Database schema/Schema.sql index a672e15ae..04acbb73d 100644 --- a/Duplicati/GUI/Database schema/Schema.sql +++ b/Duplicati/GUI/Database schema/Schema.sql @@ -83,7 +83,8 @@ CREATE TABLE "TaskFilter" ( "SortOrder" INTEGER NULL, "Include" BOOLEAN NULL, "Filter" TEXT NULL, - "TaskID" INTEGER NULL + "TaskID" INTEGER NULL, + "GlobbingFilter" TEXT NULL ); CREATE TABLE "SettingExtension" ( @@ -107,4 +108,4 @@ CREATE TABLE "EncryptionSetting" ( "Value" TEXT NULL ); -INSERT INTO "Version" ("Version") VALUES (7); \ No newline at end of file +INSERT INTO "Version" ("Version") VALUES (8); \ No newline at end of file diff --git a/Duplicati/GUI/Datamodel/Task.Extension.cs b/Duplicati/GUI/Datamodel/Task.Extension.cs index aa4e05ac4..69a92c149 100644 --- a/Duplicati/GUI/Datamodel/Task.Extension.cs +++ b/Duplicati/GUI/Datamodel/Task.Extension.cs @@ -114,6 +114,54 @@ namespace Duplicati.Datamodel get { return new TaskExtensionWrapper(this); } } + public string FilterXml + { + get + { + if (this.Filters.Count <= 0) + return ""; + + System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); + System.Xml.XmlNode root = doc.AppendChild(doc.CreateElement("root")); + + foreach (TaskFilter f in this.SortedFilters) + { + System.Xml.XmlNode e = root.AppendChild(doc.CreateElement("filter")); + e.Attributes.Append(doc.CreateAttribute("include")).Value = f.Include.ToString(); + e.Attributes.Append(doc.CreateAttribute("filter")).Value = f.Filter ?? ""; + e.Attributes.Append(doc.CreateAttribute("globbing")).Value = f.GlobbingFilter ?? ""; + } + + return doc.OuterXml; + } + set + { + if (value == this.EncodedFilter) + return; + + //Delete previous ones + this.SortedFilters = new TaskFilter[0]; + + if (string.IsNullOrEmpty(value)) + return; + + System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); + doc.LoadXml(value); + + List filters = new List(); + foreach(System.Xml.XmlNode n in doc.SelectNodes("root/filter")) + { + TaskFilter tf = this.DataParent.Add(); + tf.Include = bool.Parse(n.Attributes["include"].Value); + tf.GlobbingFilter = n.Attributes["globbing"].Value; + tf.Filter = n.Attributes["filter"].Value; + filters.Add(tf); + } + + this.SortedFilters = filters.ToArray(); + } + } + public string EncodedFilter { get @@ -127,25 +175,6 @@ namespace Duplicati.Datamodel return Library.Utility.FilenameFilter.EncodeAsFilter(filters); } - set - { - if (value == this.EncodedFilter) - return; - - //Delete previous ones - this.SortedFilters = new TaskFilter[0]; - - List filters = new List(); - foreach (KeyValuePair f in Library.Utility.FilenameFilter.DecodeFilter(value)) - { - TaskFilter tf = this.DataParent.Add(); - tf.Filter = f.Value; - tf.Include = f.Key; - filters.Add(tf); - } - - this.SortedFilters = filters.ToArray(); - } } public bool ExistsInDb diff --git a/Duplicati/GUI/Datamodel/TaskFilter.cs b/Duplicati/GUI/Datamodel/TaskFilter.cs index 44d70abbc..a20ff1b67 100644 --- a/Duplicati/GUI/Datamodel/TaskFilter.cs +++ b/Duplicati/GUI/Datamodel/TaskFilter.cs @@ -17,84 +17,93 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #endregion -/// -/// This class was created by DataClassFileBuilder (LightDatamodel) -/// -/// Table -/// Duplicati.Datamodel -/// TaskFilter -/// -/// - -using System.Data.LightDatamodel; -using System.Data.LightDatamodel.DataClassAttributes; - -namespace Duplicati.Datamodel -{ - - [DatabaseTable("TaskFilter")] - public partial class TaskFilter : DataClassBase - { - -#region " private members " - - [AutoIncrement, PrimaryKey, DatabaseField("ID")] - private System.Int64 m_ID = long.MinValue; - [DatabaseField("SortOrder")] - private System.Int64 m_SortOrder = long.MinValue; - [DatabaseField("Include")] - private System.Boolean m_Include = false; - [DatabaseField("Filter")] - private System.String m_Filter = ""; - [Relation("TaskFilterTask", typeof(Task), "ID"), DatabaseField("TaskID")] - private System.Int64 m_TaskID = long.MinValue; -#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 SortOrder - { - get{return m_SortOrder;} - set{object oldvalue = m_SortOrder;OnBeforeDataChange(this, "SortOrder", oldvalue, value);m_SortOrder = value;OnAfterDataChange(this, "SortOrder", oldvalue, value);} - } - - public System.Boolean Include - { - get{return m_Include;} - set{object oldvalue = m_Include;OnBeforeDataChange(this, "Include", oldvalue, value);m_Include = value;OnAfterDataChange(this, "Include", oldvalue, value);} - } - - public System.String Filter - { - get{return m_Filter;} - set{object oldvalue = m_Filter;OnBeforeDataChange(this, "Filter", oldvalue, value);m_Filter = value;OnAfterDataChange(this, "Filter", 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);} - } - -#endregion - -#region " referenced properties " - - [Affects(typeof(Task))] - public Task Task - { - get{ return ((DataFetcherWithRelations)m_dataparent).GetRelatedObject("TaskFilterTask", this); } - set{ ((DataFetcherWithRelations)m_dataparent).SetRelatedObject("TaskFilterTask", this, value); } - } - -#endregion - - } - +/// +/// This class was created by DataClassFileBuilder (LightDatamodel) +/// +/// Table +/// Duplicati.Datamodel +/// TaskFilter +/// +/// + +using System.Data.LightDatamodel; +using System.Data.LightDatamodel.DataClassAttributes; + +namespace Duplicati.Datamodel +{ + + [DatabaseTable("TaskFilter")] + public partial class TaskFilter : DataClassBase + { + +#region " private members " + + [AutoIncrement, PrimaryKey, DatabaseField("ID")] + private System.Int64 m_ID = long.MinValue; + [DatabaseField("SortOrder")] + private System.Int64 m_SortOrder = long.MinValue; + [DatabaseField("Include")] + private System.Boolean m_Include = false; + [DatabaseField("Filter")] + private System.String m_Filter = ""; + [Relation("TaskFilterTask", typeof(Task), "ID"), DatabaseField("TaskID")] + private System.Int64 m_TaskID = long.MinValue; + [DatabaseField("GlobbingFilter")] + private System.String m_GlobbingFilter = ""; + +#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 SortOrder + { + get{return m_SortOrder;} + set{object oldvalue = m_SortOrder;OnBeforeDataChange(this, "SortOrder", oldvalue, value);m_SortOrder = value;OnAfterDataChange(this, "SortOrder", oldvalue, value);} + } + + public System.Boolean Include + { + get{return m_Include;} + set{object oldvalue = m_Include;OnBeforeDataChange(this, "Include", oldvalue, value);m_Include = value;OnAfterDataChange(this, "Include", oldvalue, value);} + } + + public System.String Filter + { + get{return m_Filter;} + set{object oldvalue = m_Filter;OnBeforeDataChange(this, "Filter", oldvalue, value);m_Filter = value;OnAfterDataChange(this, "Filter", 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 GlobbingFilter + { + get { return m_GlobbingFilter; } + set { object oldvalue = m_GlobbingFilter; OnBeforeDataChange(this, "GlobbingFilter", oldvalue, value); m_GlobbingFilter = value; OnAfterDataChange(this, "GlobbingFilter", oldvalue, value); } + } + +#endregion + +#region " referenced properties " + + [Affects(typeof(Task))] + public Task Task + { + get{ return ((DataFetcherWithRelations)m_dataparent).GetRelatedObject("TaskFilterTask", this); } + set{ ((DataFetcherWithRelations)m_dataparent).SetRelatedObject("TaskFilterTask", this, value); } + } + +#endregion + + } + } \ No newline at end of file diff --git a/Duplicati/GUI/Duplicati.csproj b/Duplicati/GUI/Duplicati.csproj index 5809fbf59..99dc21a3a 100644 --- a/Duplicati/GUI/Duplicati.csproj +++ b/Duplicati/GUI/Duplicati.csproj @@ -1143,6 +1143,7 @@ + diff --git a/Duplicati/GUI/HelperControls/FilterDialog.Designer.cs b/Duplicati/GUI/HelperControls/FilterDialog.Designer.cs index 117640ed2..0d7eea32b 100644 --- a/Duplicati/GUI/HelperControls/FilterDialog.Designer.cs +++ b/Duplicati/GUI/HelperControls/FilterDialog.Designer.cs @@ -68,6 +68,7 @@ namespace Duplicati.GUI.HelperControls // resources.ApplyResources(this.FilterText, "FilterText"); this.FilterText.Name = "FilterText"; + this.FilterText.TextChanged += new System.EventHandler(this.FilterText_TextChanged); // // OKBtn // @@ -151,6 +152,7 @@ namespace Duplicati.GUI.HelperControls this.Controls.Add(this.Inclusive); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; this.Name = "FilterDialog"; + this.Activated += new System.EventHandler(this.FilterDialog_Activated); this.Load += new System.EventHandler(this.FilterDialog_Load); ((System.ComponentModel.ISupportInitialize)(this.HelpImage)).EndInit(); this.ResumeLayout(false); diff --git a/Duplicati/GUI/HelperControls/FilterDialog.cs b/Duplicati/GUI/HelperControls/FilterDialog.cs index f1f425e6e..e4997ba4d 100644 --- a/Duplicati/GUI/HelperControls/FilterDialog.cs +++ b/Duplicati/GUI/HelperControls/FilterDialog.cs @@ -30,15 +30,52 @@ namespace Duplicati.GUI.HelperControls { public partial class FilterDialog : Form { - KeyValuePair m_filter; + public class FilterEntry + { + public FilterEntry(bool include, string filter, string globbing) + { + this.Include = include; + this.Filter = filter; + this.Globbing = globbing; + } - public FilterDialog(KeyValuePair filter) + public string Filter; + public bool Include; + public string Globbing; + + public string DisplayValue { get { return string.IsNullOrEmpty(this.Globbing) ? this.Filter : this.Globbing; } } + public string ImageKey + { + get + { + return + (string.IsNullOrEmpty(this.Globbing) ? "regexp" : "globbing") + + "-" + + (this.Include ? "include" : "exclude"); + } + } + public override string ToString() + { + return this.DisplayValue; + } + + public ListViewItem CreateListViewItem() + { + ListViewItem lvi = new ListViewItem(this.DisplayValue, this.ImageKey); + lvi.Tag = this; + return lvi; + } + } + + FilterEntry m_filter; + + public FilterDialog(FilterEntry filter) : this() { m_filter = filter; } - public KeyValuePair Filter + public FilterEntry Filter { get { return m_filter; } } @@ -50,7 +87,8 @@ namespace Duplicati.GUI.HelperControls private void OKBtn_Click(object sender, EventArgs e) { - string f; + string filter; + string globbing; if (IsRegExp.Checked) { try @@ -62,22 +100,44 @@ namespace Duplicati.GUI.HelperControls MessageBox.Show(this, string.Format(Strings.FilterDialog.InvalidRegExpMessage, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } - f = FilterText.Text; + filter = FilterText.Text; + globbing = null; } else - f = Library.Utility.FilenameFilter.ConvertGlobbingToRegExp(FilterText.Text); + { + filter = Library.Utility.FilenameFilter.ConvertGlobbingToRegExp(FilterText.Text); + globbing = FilterText.Text; + } - m_filter = new KeyValuePair(Inclusive.Checked, f); + m_filter = new FilterEntry(Inclusive.Checked, filter, globbing); this.DialogResult = DialogResult.OK; this.Close(); } private void FilterDialog_Load(object sender, EventArgs e) { - Inclusive.Checked = m_filter.Key; - Exclusive.Checked = !m_filter.Key; - FilterText.Text = m_filter.Value; - IsRegExp.Checked = !string.IsNullOrEmpty(m_filter.Value); + Inclusive.Checked = m_filter.Include; + Exclusive.Checked = !m_filter.Include; + FilterText.Text = m_filter.Filter; + if (string.IsNullOrEmpty(m_filter.Globbing)) + { + if (string.IsNullOrEmpty(m_filter.Filter)) + { + //New filter is default globbing + IsRegExp.Checked = false; + FilterText.Text = ""; + } + else + { + IsRegExp.Checked = true; + FilterText.Text = m_filter.Filter; + } + } + else + { + IsRegExp.Checked = false; + FilterText.Text = m_filter.Globbing; + } try { FilterText.Focus(); } catch { } @@ -111,5 +171,16 @@ namespace Duplicati.GUI.HelperControls { HelpImage_Click(sender, e); } + + private void FilterText_TextChanged(object sender, EventArgs e) + { + OKBtn.Enabled = FilterText.Text!= null && FilterText.Text.Trim().Length > 0; + } + + private void FilterDialog_Activated(object sender, EventArgs e) + { + try { FilterText.Focus(); } + catch { } + } } } \ No newline at end of file diff --git a/Duplicati/GUI/HelperControls/FilterDialog.resx b/Duplicati/GUI/HelperControls/FilterDialog.resx index a69f4c3a6..79bac3150 100644 --- a/Duplicati/GUI/HelperControls/FilterDialog.resx +++ b/Duplicati/GUI/HelperControls/FilterDialog.resx @@ -156,7 +156,7 @@ 170, 17 - 1 + 2 Exclude files matching the filter @@ -183,7 +183,7 @@ 29, 13 - 2 + 3 Filter @@ -207,7 +207,7 @@ 272, 20 - 3 + 5 FilterText @@ -221,6 +221,9 @@ 4 + + False + 112, 96 @@ -228,7 +231,7 @@ 75, 23 - 4 + 8 OK @@ -252,7 +255,7 @@ 75, 23 - 5 + 9 Cancel @@ -279,7 +282,7 @@ 146, 17 - 6 + 4 Filter is regular expression @@ -307,7 +310,7 @@ 24, 24 - 7 + 6 BrowseFolderButton @@ -334,7 +337,7 @@ 24, 24 - 8 + 7 ... @@ -376,7 +379,7 @@ 52, 13 - 9 + 1 Filter help diff --git a/Duplicati/GUI/HelperControls/FilterEditor.Designer.cs b/Duplicati/GUI/HelperControls/FilterEditor.Designer.cs index ffc2c8d27..cd37b3d9a 100644 --- a/Duplicati/GUI/HelperControls/FilterEditor.Designer.cs +++ b/Duplicati/GUI/HelperControls/FilterEditor.Designer.cs @@ -28,74 +28,76 @@ namespace Duplicati.GUI.HelperControls /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FilterEditor)); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.listView = new System.Windows.Forms.ListView(); - this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.imageList = new System.Windows.Forms.ImageList(this.components); - this.toolStrip1 = new System.Windows.Forms.ToolStrip(); - this.AddFilterButton = new System.Windows.Forms.ToolStripButton(); - this.RemoveFilterButton = new System.Windows.Forms.ToolStripButton(); - this.EditFilterButton = new System.Windows.Forms.ToolStripButton(); - this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - this.IncludeFolderButton = new System.Windows.Forms.ToolStripButton(); - this.ExcludeFolderButton = new System.Windows.Forms.ToolStripButton(); - this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.MoveFilterUpButton = new System.Windows.Forms.ToolStripButton(); - this.MoveFilterDownButton = new System.Windows.Forms.ToolStripButton(); - this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.MoveFilterTopButton = new System.Windows.Forms.ToolStripButton(); - this.MoveFilterBottomButton = new System.Windows.Forms.ToolStripButton(); - this.HelpButton = new System.Windows.Forms.ToolStripButton(); - this.btnTestSearch = new System.Windows.Forms.Button(); - this.label1 = new System.Windows.Forms.Label(); - this.FilenameTester = new System.Windows.Forms.TextBox(); - this.toolTip = new System.Windows.Forms.ToolTip(this.components); - this.TestResults = new System.Windows.Forms.PictureBox(); - this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); - this.groupBox1.SuspendLayout(); - this.toolStrip1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.TestResults)).BeginInit(); - this.SuspendLayout(); - // - // groupBox1 - // - resources.ApplyResources(this.groupBox1, "groupBox1"); - this.groupBox1.Controls.Add(this.listView); - this.groupBox1.Controls.Add(this.toolStrip1); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.TabStop = false; - // - // listView - // - this.listView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FilterEditor)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.listView = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.imageList = new System.Windows.Forms.ImageList(this.components); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.AddFilterButton = new System.Windows.Forms.ToolStripButton(); + this.RemoveFilterButton = new System.Windows.Forms.ToolStripButton(); + this.EditFilterButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.IncludeFolderButton = new System.Windows.Forms.ToolStripButton(); + this.ExcludeFolderButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.MoveFilterUpButton = new System.Windows.Forms.ToolStripButton(); + this.MoveFilterDownButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.MoveFilterTopButton = new System.Windows.Forms.ToolStripButton(); + this.MoveFilterBottomButton = new System.Windows.Forms.ToolStripButton(); + this.HelpButton = new System.Windows.Forms.ToolStripButton(); + this.btnTestSearch = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.FilenameTester = new System.Windows.Forms.TextBox(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.TestResults = new System.Windows.Forms.PictureBox(); + this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.groupBox1.SuspendLayout(); + this.toolStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.TestResults)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.listView); + this.groupBox1.Controls.Add(this.toolStrip1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // listView + // + this.listView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.columnHeader1}); - resources.ApplyResources(this.listView, "listView"); - this.listView.FullRowSelect = true; - this.listView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; - this.listView.Name = "listView"; - this.listView.SmallImageList = this.imageList; - this.listView.UseCompatibleStateImageBehavior = false; - this.listView.View = System.Windows.Forms.View.Details; - this.listView.SelectedIndexChanged += new System.EventHandler(this.listView_SelectedIndexChanged); - this.listView.DoubleClick += new System.EventHandler(this.listView_DoubleClick); - // - // columnHeader1 - // - resources.ApplyResources(this.columnHeader1, "columnHeader1"); - // - // imageList - // - this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream"))); - this.imageList.TransparentColor = System.Drawing.Color.Transparent; - this.imageList.Images.SetKeyName(0, "Inclusion.ico"); - this.imageList.Images.SetKeyName(1, "Exclusion.ico"); - // - // toolStrip1 - // - this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; - this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + resources.ApplyResources(this.listView, "listView"); + this.listView.FullRowSelect = true; + this.listView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; + this.listView.Name = "listView"; + this.listView.SmallImageList = this.imageList; + this.listView.UseCompatibleStateImageBehavior = false; + this.listView.View = System.Windows.Forms.View.Details; + this.listView.SelectedIndexChanged += new System.EventHandler(this.listView_SelectedIndexChanged); + this.listView.DoubleClick += new System.EventHandler(this.listView_DoubleClick); + // + // columnHeader1 + // + resources.ApplyResources(this.columnHeader1, "columnHeader1"); + // + // imageList + // + this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream"))); + this.imageList.TransparentColor = System.Drawing.Color.Transparent; + this.imageList.Images.SetKeyName(0, "globbing-include"); + this.imageList.Images.SetKeyName(1, "globbing-exclude"); + this.imageList.Images.SetKeyName(2, "regexp-include"); + this.imageList.Images.SetKeyName(3, "regexp-exclude"); + // + // toolStrip1 + // + this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.AddFilterButton, this.RemoveFilterButton, this.EditFilterButton, @@ -109,144 +111,144 @@ namespace Duplicati.GUI.HelperControls this.MoveFilterTopButton, this.MoveFilterBottomButton, this.HelpButton}); - resources.ApplyResources(this.toolStrip1, "toolStrip1"); - this.toolStrip1.Name = "toolStrip1"; - this.toolStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; - // - // AddFilterButton - // - this.AddFilterButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - resources.ApplyResources(this.AddFilterButton, "AddFilterButton"); - this.AddFilterButton.Name = "AddFilterButton"; - this.AddFilterButton.Click += new System.EventHandler(this.AddFilterButton_Click); - // - // RemoveFilterButton - // - this.RemoveFilterButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - resources.ApplyResources(this.RemoveFilterButton, "RemoveFilterButton"); - this.RemoveFilterButton.Name = "RemoveFilterButton"; - this.RemoveFilterButton.Click += new System.EventHandler(this.RemoveFilterButton_Click); - // - // EditFilterButton - // - this.EditFilterButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - resources.ApplyResources(this.EditFilterButton, "EditFilterButton"); - this.EditFilterButton.Name = "EditFilterButton"; - this.EditFilterButton.Click += new System.EventHandler(this.EditFilterButton_Click); - // - // toolStripSeparator3 - // - this.toolStripSeparator3.Name = "toolStripSeparator3"; - resources.ApplyResources(this.toolStripSeparator3, "toolStripSeparator3"); - // - // IncludeFolderButton - // - this.IncludeFolderButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.IncludeFolderButton.Image = global::Duplicati.GUI.Properties.Resources.AddedFolder; - resources.ApplyResources(this.IncludeFolderButton, "IncludeFolderButton"); - this.IncludeFolderButton.Name = "IncludeFolderButton"; - this.IncludeFolderButton.Click += new System.EventHandler(this.IncludeFolderButton_Click); - // - // ExcludeFolderButton - // - this.ExcludeFolderButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.ExcludeFolderButton.Image = global::Duplicati.GUI.Properties.Resources.DeletedFolder; - resources.ApplyResources(this.ExcludeFolderButton, "ExcludeFolderButton"); - this.ExcludeFolderButton.Name = "ExcludeFolderButton"; - this.ExcludeFolderButton.Click += new System.EventHandler(this.ExcludeFolderButton_Click); - // - // toolStripSeparator1 - // - this.toolStripSeparator1.Name = "toolStripSeparator1"; - resources.ApplyResources(this.toolStripSeparator1, "toolStripSeparator1"); - // - // MoveFilterUpButton - // - this.MoveFilterUpButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - resources.ApplyResources(this.MoveFilterUpButton, "MoveFilterUpButton"); - this.MoveFilterUpButton.Name = "MoveFilterUpButton"; - this.MoveFilterUpButton.Click += new System.EventHandler(this.MoveFilterUpButton_Click); - // - // MoveFilterDownButton - // - this.MoveFilterDownButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - resources.ApplyResources(this.MoveFilterDownButton, "MoveFilterDownButton"); - this.MoveFilterDownButton.Name = "MoveFilterDownButton"; - this.MoveFilterDownButton.Click += new System.EventHandler(this.MoveFilterDownButton_Click); - // - // toolStripSeparator2 - // - this.toolStripSeparator2.Name = "toolStripSeparator2"; - resources.ApplyResources(this.toolStripSeparator2, "toolStripSeparator2"); - // - // MoveFilterTopButton - // - this.MoveFilterTopButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - resources.ApplyResources(this.MoveFilterTopButton, "MoveFilterTopButton"); - this.MoveFilterTopButton.Name = "MoveFilterTopButton"; - this.MoveFilterTopButton.Click += new System.EventHandler(this.MoveFilterTopButton_Click); - // - // MoveFilterBottomButton - // - this.MoveFilterBottomButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - resources.ApplyResources(this.MoveFilterBottomButton, "MoveFilterBottomButton"); - this.MoveFilterBottomButton.Name = "MoveFilterBottomButton"; - this.MoveFilterBottomButton.Click += new System.EventHandler(this.MoveFilterBottomButton_Click); - // - // HelpButton - // - this.HelpButton.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; - this.HelpButton.Image = global::Duplicati.GUI.Properties.Resources.help; - resources.ApplyResources(this.HelpButton, "HelpButton"); - this.HelpButton.Name = "HelpButton"; - this.HelpButton.Click += new System.EventHandler(this.HelpButton_Click); - // - // btnTestSearch - // - resources.ApplyResources(this.btnTestSearch, "btnTestSearch"); - this.btnTestSearch.Name = "btnTestSearch"; - this.btnTestSearch.UseVisualStyleBackColor = true; - this.btnTestSearch.Click += new System.EventHandler(this.btnTestSearch_Click); - // - // label1 - // - resources.ApplyResources(this.label1, "label1"); - this.label1.Name = "label1"; - // - // FilenameTester - // - resources.ApplyResources(this.FilenameTester, "FilenameTester"); - this.FilenameTester.Name = "FilenameTester"; - this.FilenameTester.TextChanged += new System.EventHandler(this.FilenameTester_TextChanged); - // - // TestResults - // - resources.ApplyResources(this.TestResults, "TestResults"); - this.TestResults.Name = "TestResults"; - this.TestResults.TabStop = false; - // - // folderBrowserDialog - // - this.folderBrowserDialog.ShowNewFolderButton = false; - // - // FilterEditor - // - resources.ApplyResources(this, "$this"); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.btnTestSearch); - this.Controls.Add(this.TestResults); - this.Controls.Add(this.FilenameTester); - this.Controls.Add(this.label1); - this.Controls.Add(this.groupBox1); - this.Name = "FilterEditor"; - this.Load += new System.EventHandler(this.FilterEditor_Load); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); - this.toolStrip1.ResumeLayout(false); - this.toolStrip1.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.TestResults)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); + resources.ApplyResources(this.toolStrip1, "toolStrip1"); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; + // + // AddFilterButton + // + this.AddFilterButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.AddFilterButton, "AddFilterButton"); + this.AddFilterButton.Name = "AddFilterButton"; + this.AddFilterButton.Click += new System.EventHandler(this.AddFilterButton_Click); + // + // RemoveFilterButton + // + this.RemoveFilterButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.RemoveFilterButton, "RemoveFilterButton"); + this.RemoveFilterButton.Name = "RemoveFilterButton"; + this.RemoveFilterButton.Click += new System.EventHandler(this.RemoveFilterButton_Click); + // + // EditFilterButton + // + this.EditFilterButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.EditFilterButton, "EditFilterButton"); + this.EditFilterButton.Name = "EditFilterButton"; + this.EditFilterButton.Click += new System.EventHandler(this.EditFilterButton_Click); + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + resources.ApplyResources(this.toolStripSeparator3, "toolStripSeparator3"); + // + // IncludeFolderButton + // + this.IncludeFolderButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.IncludeFolderButton.Image = global::Duplicati.GUI.Properties.Resources.AddedFolder; + resources.ApplyResources(this.IncludeFolderButton, "IncludeFolderButton"); + this.IncludeFolderButton.Name = "IncludeFolderButton"; + this.IncludeFolderButton.Click += new System.EventHandler(this.IncludeFolderButton_Click); + // + // ExcludeFolderButton + // + this.ExcludeFolderButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ExcludeFolderButton.Image = global::Duplicati.GUI.Properties.Resources.DeletedFolder; + resources.ApplyResources(this.ExcludeFolderButton, "ExcludeFolderButton"); + this.ExcludeFolderButton.Name = "ExcludeFolderButton"; + this.ExcludeFolderButton.Click += new System.EventHandler(this.ExcludeFolderButton_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + resources.ApplyResources(this.toolStripSeparator1, "toolStripSeparator1"); + // + // MoveFilterUpButton + // + this.MoveFilterUpButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.MoveFilterUpButton, "MoveFilterUpButton"); + this.MoveFilterUpButton.Name = "MoveFilterUpButton"; + this.MoveFilterUpButton.Click += new System.EventHandler(this.MoveFilterUpButton_Click); + // + // MoveFilterDownButton + // + this.MoveFilterDownButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.MoveFilterDownButton, "MoveFilterDownButton"); + this.MoveFilterDownButton.Name = "MoveFilterDownButton"; + this.MoveFilterDownButton.Click += new System.EventHandler(this.MoveFilterDownButton_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + resources.ApplyResources(this.toolStripSeparator2, "toolStripSeparator2"); + // + // MoveFilterTopButton + // + this.MoveFilterTopButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.MoveFilterTopButton, "MoveFilterTopButton"); + this.MoveFilterTopButton.Name = "MoveFilterTopButton"; + this.MoveFilterTopButton.Click += new System.EventHandler(this.MoveFilterTopButton_Click); + // + // MoveFilterBottomButton + // + this.MoveFilterBottomButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.MoveFilterBottomButton, "MoveFilterBottomButton"); + this.MoveFilterBottomButton.Name = "MoveFilterBottomButton"; + this.MoveFilterBottomButton.Click += new System.EventHandler(this.MoveFilterBottomButton_Click); + // + // HelpButton + // + this.HelpButton.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.HelpButton.Image = global::Duplicati.GUI.Properties.Resources.help; + resources.ApplyResources(this.HelpButton, "HelpButton"); + this.HelpButton.Name = "HelpButton"; + this.HelpButton.Click += new System.EventHandler(this.HelpButton_Click); + // + // btnTestSearch + // + resources.ApplyResources(this.btnTestSearch, "btnTestSearch"); + this.btnTestSearch.Name = "btnTestSearch"; + this.btnTestSearch.UseVisualStyleBackColor = true; + this.btnTestSearch.Click += new System.EventHandler(this.btnTestSearch_Click); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // FilenameTester + // + resources.ApplyResources(this.FilenameTester, "FilenameTester"); + this.FilenameTester.Name = "FilenameTester"; + this.FilenameTester.TextChanged += new System.EventHandler(this.FilenameTester_TextChanged); + // + // TestResults + // + resources.ApplyResources(this.TestResults, "TestResults"); + this.TestResults.Name = "TestResults"; + this.TestResults.TabStop = false; + // + // folderBrowserDialog + // + this.folderBrowserDialog.ShowNewFolderButton = false; + // + // FilterEditor + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.btnTestSearch); + this.Controls.Add(this.TestResults); + this.Controls.Add(this.FilenameTester); + this.Controls.Add(this.label1); + this.Controls.Add(this.groupBox1); + this.Name = "FilterEditor"; + this.Load += new System.EventHandler(this.FilterEditor_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.TestResults)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); } diff --git a/Duplicati/GUI/HelperControls/FilterEditor.cs b/Duplicati/GUI/HelperControls/FilterEditor.cs index 84aaacead..05d91e2ba 100644 --- a/Duplicati/GUI/HelperControls/FilterEditor.cs +++ b/Duplicati/GUI/HelperControls/FilterEditor.cs @@ -50,33 +50,61 @@ namespace Duplicati.GUI.HelperControls /// /// if set to true include dynamic filters. /// A list of filters - private List> GetFilterList(bool includeDynamicFilters) + private List GetFilterList(bool includeDynamicFilters) { - List> filters = new List>(); + List filters = new List(); foreach (ListViewItem lvi in listView.Items) - filters.Add(new KeyValuePair(lvi.ImageIndex == 0, lvi.Text)); + filters.Add(lvi.Tag as FilterDialog.FilterEntry); if (includeDynamicFilters && !string.IsNullOrEmpty(m_dynamicFilter)) { - List> tmp = Library.Utility.FilenameFilter.DecodeFilter(m_dynamicFilter); - tmp.AddRange(filters); - filters = tmp; + List> tmp1 = Library.Utility.FilenameFilter.DecodeFilter(m_dynamicFilter); + List tmp2 = new List(); + foreach (KeyValuePair k in tmp1) + tmp2.Add(new FilterDialog.FilterEntry(k.Key, k.Value, null)); + tmp2.AddRange(filters); + filters = tmp2; } return filters; } + private string EncodeAsFilter(List items) + { + List> r = new List>(); + foreach (FilterDialog.FilterEntry f in items) + r.Add(new KeyValuePair(f.Include, f.Filter)); + + return Duplicati.Library.Utility.FilenameFilter.EncodeAsFilter(r); + } + /// /// Gets or sets the filter string as displayed in the UI /// [DefaultValue("")] - public string Filter + public string FilterXml { - get { return Library.Utility.FilenameFilter.EncodeAsFilter(GetFilterList(false)); } + get { return EncodeFilterAsXml(GetFilterList(false)); } set { m_filter = value; RefreshList(); FilenameTester_TextChanged(null, null); } } + private string EncodeFilterAsXml(List list) + { + System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); + System.Xml.XmlNode root = doc.AppendChild(doc.CreateElement("root")); + + foreach (FilterDialog.FilterEntry f in list) + { + System.Xml.XmlNode filter = root.AppendChild(doc.CreateElement("filter")); + filter.Attributes.Append(doc.CreateAttribute("include")).Value = f.Include.ToString(); + filter.Attributes.Append(doc.CreateAttribute("filter")).Value = f.Filter; + filter.Attributes.Append(doc.CreateAttribute("globbing")).Value = f.Globbing; + } + + return doc.OuterXml; + } + /// /// Gets or sets the dynamic filter, which is applied to the test area, but not visible in the list /// @@ -103,13 +131,33 @@ namespace Duplicati.GUI.HelperControls private void RefreshList() { listView.Items.Clear(); - foreach (KeyValuePair f in Library.Utility.FilenameFilter.DecodeFilter(m_filter)) - listView.Items.Add(f.Value, f.Key ? 0 : 1); + foreach (FilterDialog.FilterEntry f in DecodeFilter(m_filter)) + listView.Items.Add(f.CreateListViewItem()); if (listView.Items.Count > 0) listView.Items[0].Selected = true; } + private List DecodeFilter(string filter) + { + List res = new List(); + if (string.IsNullOrEmpty(filter)) + return res; + + System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); + doc.LoadXml(filter); + foreach (System.Xml.XmlNode n in doc.SelectNodes("root/filter")) + { + res.Add(new FilterDialog.FilterEntry( + bool.Parse(n.Attributes["include"].Value), + n.Attributes["filter"].Value, + n.Attributes["globbing"].Value + )); + } + + return res; + } + /// /// Handles the TextChanged event of the FilenameTester control. /// Used to update the status and tooltip to show if the current path is included or excluded @@ -194,7 +242,8 @@ namespace Duplicati.GUI.HelperControls parentFolders.Reverse(); //Test if any of the parent folders are excluded - Library.Utility.FilenameFilter fn = new Duplicati.Library.Utility.FilenameFilter(GetFilterList(true)); + string compact = EncodeAsFilter(GetFilterList(true)); + Library.Utility.FilenameFilter fn = new Duplicati.Library.Utility.FilenameFilter(Duplicati.Library.Utility.FilenameFilter.DecodeFilter(compact)); Library.Utility.IFilenameFilter match; foreach (string s in parentFolders) { @@ -275,13 +324,14 @@ namespace Duplicati.GUI.HelperControls /// The instance containing the event data. private void EditFilterButton_Click(object sender, EventArgs e) { - if (listView.SelectedItems.Count == 1) + if (listView.SelectedItems.Count == 1 && listView.SelectedItems[0].Tag is FilterDialog.FilterEntry) { - FilterDialog dlg = new FilterDialog(new KeyValuePair(listView.SelectedItems[0].ImageIndex == 0, listView.SelectedItems[0].Text)); + FilterDialog dlg = new FilterDialog((FilterDialog.FilterEntry)listView.SelectedItems[0].Tag); if (dlg.ShowDialog(this) == DialogResult.OK) { - listView.SelectedItems[0].Text = dlg.Filter.Value; - listView.SelectedItems[0].ImageIndex = dlg.Filter.Key ? 0 : 1; + listView.SelectedItems[0].Tag = dlg.Filter; + listView.SelectedItems[0].Text = dlg.Filter.DisplayValue; + listView.SelectedItems[0].ImageKey = dlg.Filter.ImageKey; FilenameTester_TextChanged(sender, e); } } @@ -366,10 +416,10 @@ namespace Duplicati.GUI.HelperControls /// The instance containing the event data. private void AddFilterButton_Click(object sender, EventArgs e) { - FilterDialog dlg = new FilterDialog(new KeyValuePair(true, "")); + FilterDialog dlg = new FilterDialog(new FilterDialog.FilterEntry(false, null, null)); if (dlg.ShowDialog(this) == DialogResult.OK) { - listView.Items.Add(dlg.Filter.Value, dlg.Filter.Key ? 0 : 1); + listView.Items.Add(dlg.Filter.CreateListViewItem()); FilenameTester_TextChanged(sender, e); } } @@ -417,7 +467,9 @@ namespace Duplicati.GUI.HelperControls folderBrowserDialog.Description = Strings.FilterEditor.IncludeFolderBrowseTitle; if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK) { - listView.Items.Add(Duplicati.Library.Utility.FilenameFilter.ConvertGlobbingToRegExp(Duplicati.Library.Utility.Utility.AppendDirSeparator(folderBrowserDialog.SelectedPath)), 0); + string path = Duplicati.Library.Utility.Utility.AppendDirSeparator(folderBrowserDialog.SelectedPath); + FilterDialog.FilterEntry fe = new FilterDialog.FilterEntry(true, Duplicati.Library.Utility.FilenameFilter.ConvertGlobbingToRegExp(path), path); + listView.Items.Add(fe.CreateListViewItem()); FilenameTester_TextChanged(sender, e); } } @@ -432,7 +484,9 @@ namespace Duplicati.GUI.HelperControls folderBrowserDialog.Description = Strings.FilterEditor.ExcludeFolderBrowseTitle; if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK) { - listView.Items.Add(Duplicati.Library.Utility.FilenameFilter.ConvertGlobbingToRegExp(Duplicati.Library.Utility.Utility.AppendDirSeparator(folderBrowserDialog.SelectedPath)), 1); + string path = Duplicati.Library.Utility.Utility.AppendDirSeparator(folderBrowserDialog.SelectedPath); + FilterDialog.FilterEntry fe = new FilterDialog.FilterEntry(false, Duplicati.Library.Utility.FilenameFilter.ConvertGlobbingToRegExp(path), path); + listView.Items.Add(fe.CreateListViewItem()); FilenameTester_TextChanged(sender, e); } } @@ -447,9 +501,7 @@ namespace Duplicati.GUI.HelperControls { listView.Items.Clear(); foreach (var filter in dlg.Filters) - { - listView.Items.Add(filter.Value, filter.Key ? 0 : 1); - } + listView.Items.Add(filter.CreateListViewItem()); } } diff --git a/Duplicati/GUI/HelperControls/FilterEditor.resx b/Duplicati/GUI/HelperControls/FilterEditor.resx index 27332b10d..9143cc729 100644 --- a/Duplicati/GUI/HelperControls/FilterEditor.resx +++ b/Duplicati/GUI/HelperControls/FilterEditor.resx @@ -142,27 +142,57 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACC - BAAAAk1TRnQBSQFMAgEBAgEAATwBAAE8AQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA - AwABEAMAAQEBAAEgBgABEP8AKwADEwEaASwCKwFDASwCKwFDASwCKwFD8AADVQGyAVIB4gGMAf8BUQHh - AYkB/wFDAcgBawH/8AADVQGyAUYB1AFmAf8BPQHLAU0B/wFDAckBawH/8AADVQGyAU4B2gFwAf8BPgHM - AU8B/wFDAcoBawH/8AADVQGyAVoB4wGBAf8BSgHUAVwB/wFEAcsBbAH/4AABPgGaATwB/gFNAdMBcgH/ - AU0B1AF0Af8BTgHUAXQB/wFNAdMBcwH/AWYB6gGEAf8BWQHfAWwB/wFXAeMBkAH/AUQBygFqAf8BQgHI - AWkB/wFBAcYBZwH/AUEBxQFnAf8DMAFMDAADSAGEAkkB0wH/AksB1AH/Ak0B1AH/Ak4B0wH/Ak0B0AH/ - AkoBzAH/AkYBxwH/AkIBwwH/AkABwgH/AkABwgH/Ai8BqAH/kAABQQGfAUEB/gFiAdoBdQH/AWsB5AGB - Af8BcQHsAYYB/wF0AfABigH/AXEB7wGHAf8BaAHqAYEB/wFbAeEBbwH/AU4B1wFgAf8BQgHOAVMB/wE9 - AcsBTQH/AVAB4AGHAf8DMAFMDAADSAGEAlsB1wH/AmIB1gH/Am4B5AH/AnYB7gH/AnYB8AH/AmoB6QH/ - AlcB3AH/AkcB0AH/AkIBzAH/AkIBzAH/AjkBtwH/kAABQQGgAUEB/gFbAdYBgQH/AWMB3wGFAf8BagHn - AY0B/wFvAe4BkwH/AXQB7wGKAf8BcgHwAYgB/wFqAewBhgH/AV8B5wGCAf8BVAHeAXYB/wFKAdcBawH/ - AVEB4QGKAf8DMAFMDAADSAGEAlwB2gH/AmMB3QH/Am0B6AH/AnMB8AH/AnMB8gH/AmoB7AH/AlsB4gH/ - Ak0B2AH/AkgB1AH/AkgB1AH/AjkBtwH/kAABVgJVAbEDVQG1A1UBtQNVAbUBVwFSAUkB6AFvAe0BkwH/ - AXQB7wGJAf8BUAHWAYEB/wNVAbUDVQG1A1UBtQNVAbUDGAEhDAADLQFGA1UBtQNVAbUDVQG1A1UBtQNV - AbUDVQG1A1UBtQNVAbUDVQG1A1UBtQFWAlUBtKAAA1UBsgFoAeUBiwH/AW8B6AGDAf8BUAHWAYEB//AA - A1UBsgFfAdsBgQH/AWYB3gGAAf8BTwHVAXgB//AAA1UBsgFWAdIBdwH/AVsB0wFuAf8BTgHUAXYB//AA - A1QBqwExAbkBNgH/ATEBuAE2Af8BLwG1ATIB//8A/wDaAAFCAU0BPgcAAT4DAAEoAwABQAMAARADAAEB - AQABAQUAAYAXAAP/AQAE/wQAAfwBPwL/BAAB/AE/Av8EAAH8AT8C/wQAAfwBPwL/BAAB/AE/Av8EAAHA - AQEBwAEDBAABwAEBAcABAwQAAcABAQHAAQMEAAHAAQEBwAEDBAAB/AE/Av8EAAH8AT8C/wQAAfwBPwL/ - BAAB/AE/Av8EAAT/BAAE/wQACw== + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACg + CwAAAk1TRnQBSQFMAgEBBAEAAUQBAAFEAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wA7AAMTARoBLAIr + AUMBLAIrAUMBLAIrAUPwAANVAbIBUQHiAYwB/wFQAeEBiQH/AUIByAFqAf/wAANVAbIBRQHUAWUB/wE8 + AcsBTAH/AUIByQFqAf9cAAEoAaQBKAH/ASgBpAEoAf8MAAEtAZoBLgH2ASgBpAEoAf8BKgGiASsB/QEo + AaQBKAH/ASIBJgEiATEIAAMIAQsBKAGkASgB/wEoAaQBKAH/BAACKAGkAf8CKAGkAf8MAAItAZ0B9gIo + AaQB/wIqAaMB/QIoAaQB/wIiASYBMQgAAggBCQELAigBpAH/AigBpAH/GAADVQGyAU0B2gFvAf8BPQHM + AU4B/wFCAcoBagH/XAABQgHIAWUB/wFNAdgBfgH/CAABJgErASYBOAFGAdEBaQH/AT4BxQFXAf8BLwGW + ATMB7gFNAdwBeAH/ASoBpwEtAf8IAAEqAaIBKwH9AVsB6wGfAf8BKAGkASgB/wQAAkoByAH/AlsB2gH/ + CAACJgErATgCUAHTAf8CRQHGAf8BLwExAZgB7gJZAd0B/wIrAacB/wgAAioBowH9Am0B7AH/AikBogH+ + GAADVQGyAVkB4wGBAf8BSQHUAVsB/wFDAcsBawH/XAABQQHHAWIB/wFMAdYBeQH/CAABKAGkASgB/wFK + AdkBcQH/ATABmAEzAfEEAAEtAawBNAH/AUsB2gFzAf8BOgGHAT0BzgFAAWEBRAGMAVIB4AGIAf8BPAHA + AVYB/wEMAQ0BDAEQBAACSgHIAf8CWgHYAf8IAAIoAaQB/wFVAVQB2gH/ATABMQGaAfEEAAIvAa0B/wJX + AdwB/wE6AT0BiAHOAUABQgFhAYwCYgHjAf8CRAHCAf8CDAENARAIAAE+AZgBPAH+AUwB0wFxAf8BTAHU + AXMB/wFNAdQBcwH/AUwB0wFyAf8BZQHqAYQB/wFYAd8BawH/AVYB4wGQAf8BQwHKAWkB/wFBAcgBaAH/ + AUABxgFmAf8BQAHFAWYB/wMwAUwMAANIAYQCSAHTAf8CSgHUAf8CTAHUAf8CTQHTAf8CTAHQAf8CSQHM + Af8CRQHHAf8CQQHDAf8CPwHCAf8CPwHCAf8CLgGoAf8MAAFBAcYBYQH/AUsB1QF3Af8BKQExASkCPwF0 + AUUBrwFGAdIBaAH/AToBwAFNAf8BDgEPAQ4BEwQAATUBQgE3AVoBQQHMAV4B/wE9AcUBVgH/ATUBtwFF + Af8BUgHgAYcB/wFBAW0BRQGhCAACSgHIAf8CWAHXAf8CKQExAj8BQgF2Aa8CTwHUAf8CPwHCAf8CDgEP + ARMEAAE1ATYBQwFaAkoBzgH/AkUBxwH/AjoBuAH/AmIB4wH/AUEBRAFvAaEMAAFBAZ0BQQH+AWEB2gF0 + Af8BagHkAYEB/wFwAewBhgH/AXMB8AGKAf8BcAHvAYcB/wFnAeoBgQH/AVoB4QFuAf8BTQHXAV8B/wFB + Ac4BUgH/ATwBywFMAf8BTwHgAYcB/wMwAUwMAANIAYQCWgHXAf8CYQHWAf8CbQHkAf8CdQHuAf8CdQHw + Af8CaQHpAf8CVgHcAf8CRgHQAf8CQQHMAf8CQQHMAf8COAG3Af8MAAFAAcYBYAH/AVUB5QGPAf8BUQHg + AYQB/wFNAdwBeAH/AUMBzgFgAf8BNAGTATcB5gwAATIBlgE1AesBSwHZAXIB/wFPAd4BfQH/ASgBpAEo + Af8MAAJKAccB/wJnAecB/wJgAeIB/wJZAd4B/wFMAUsB0AH/ATQBNgGUAeYMAAEyATUBlwHrAlcB2wH/ + Al0B4AH/AigBpAH/EAABQQGeAUEB/gFaAdYBgQH/AWIB3wGFAf8BaQHnAY0B/wFuAe4BkwH/AXMB7wGK + Af8BcQHwAYgB/wFpAewBhgH/AV4B5wGCAf8BUwHeAXUB/wFJAdcBagH/AVAB4QGKAf8DMAFMDAADSAGE + AlsB2gH/AmIB3QH/AmwB6AH/AnIB8AH/AnIB8gH/AmkB7AH/AloB4gH/AkwB2AH/AkcB1AH/AkcB1AH/ + AjgBtwH/DAABQAHGAWAB/wFKAdUBdQH/ASgBpAEoAf8BKAGlASkB/wFHAdUBaQH/ATgBvwFKAf8DCQEM + CAABPwFcAUQBhQFHAdQBagH/AU8B3gF8Af8BLQGeAS8B9wwAAkoBxwH/AlcB1gH/AigBpAH/AikBpQH/ + AVIBUQHXAf8CPgHBAf8DCQEMCAABPwFBAV4BhQJSAdYB/wJdAeAB/wEtAS4BnwH3EAABVgJVAbEDVQG1 + A1UBtQNVAbUBVwFVAU0B6AFuAe0BkwH/AXMB7wGJAf8BTwHWAYEB/wNVAbUDVQG1A1UBtQNVAbUDGAEh + DAADLQFGA1UBtQNVAbUDVQG1A1UBtQNVAbUDVQG1A1UBtQNVAbUDVQG1A1UBtQFWAlUBtAwAAUEBxgFg + Af8BSgHVAXYB/wgAATEBswE8Af8BRgHVAWYB/wE2AUYBOAFfBAADBAEGATEBswE8Af8BSgHYAXAB/wE7 + AcEBUwH/AU4B2wF9Af8BPQFWAUEBeQgAAkoByAH/AlgB1wH/CAACNQG0Af8CUAHXAf8BNgE3AUcBXwQA + AwQBBgI1AbQB/wJXAdsB/wJDAcMB/wJdAd4B/wE9AUABVwF5HAADVQGyAWcB5QGLAf8BbgHoAYMB/wFP + AdYBgQH/XAABQQHHAWIB/wFLAdYBeAH/AUEBcQFBAZ8BOgGGAUAB0AFDAc4BYwH/AUYB0wFnAf8BJgEr + ASYBOAQAASkBnQErAfsBSgHZAXEB/wEoAaQBKAH/AT8BeAFEAbQBVAHjAYwB/wE1AbYBRQH/AwMBBAQA + AkoByAH/AloB2AH/AkEBcQGfAToBPgGJAdACTgHQAf8CUQHVAf8CJgErATgEAAEpASoBngH7AlcB3AH/ + AigBpAH/AT8BQgF6AbQCZgHmAf8COgG3Af8DAwEEGAADVQGyAV4B2wGBAf8BZQHeAYAB/wFOAdUBdwH/ + XAABQgHIAWQB/wFZAekBmQH/AVUB5QGPAf8BUgHhAYYB/wFOAdwBewH/ASkBoAEqAf4EAAE/AV0BQwGE + AUgB1gFuAf8BOAG8AUsB/wEOAQ8BDgETBAABKAGlASkB/wFbAeoBnQH/ASoBnQErAfkEAAJKAcgB/wJs + AesB/wJoAegB/wJjAeQB/wJdAeAB/wIpAaIB/gQAAT8BQQFeAYQCVQHZAf8CPwG+Af8CDgEPARMEAAIp + AaUB/wJtAewB/wEqASsBngH5GAADVQGyAVUB0gF2Af8BWgHTAW0B/wFNAdQBdQH/XAABPgGBAT4BuwE+ + AYQBPgG/AT4BhAE+Ab8BPgF8AUMBuwE4AUoBOgFlCAABMQE9ATMBUQE+AYIBPgG/AT0BVgFAAXgIAAER + ARIBEQEXAT4BggE+Ab8BQQF2AUIBrAQAAj4BgQG7Aj4BhAG/Aj4BhAG/AT4BQAF/AbsBOAE5AUoBZQgA + ATEBMgE9AVECPgGCAb8BPQE/AVcBeAgAAhEBEgEXAj4BggG/AkEBeAGsGAADVAGrATABuQE1Af8BMAG4 + ATUB/wEuAbUBMQH//wD/ANoAAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEBBgABARYAA/+BAAj/ + AfwBPwb/AfwBPwb/AfwBPwL/AZwBGAGcARgB/AE/Av8BmAEYAZgBGAH8AT8C/wGYAYABmAGAAcABAQHA + AQMBgAGBAYABgQHAAQEBwAEDAYEBwwGBAcMBwAEBAcABAwGAAcMBgAHDAcABAQHAAQMBmAGBAZgBgQH8 + AT8C/wSAAfwBPwL/AYEBCAGBAQgB/AE/Av8BgwEYAYMBGAH8AT8W/ws= @@ -416,7 +446,7 @@ Magenta - 72, 22 + 79, 22 Filter help diff --git a/Duplicati/GUI/HelperControls/TestSearchSelection.Designer.cs b/Duplicati/GUI/HelperControls/TestSearchSelection.Designer.cs index fa06978df..4199f0ea5 100644 --- a/Duplicati/GUI/HelperControls/TestSearchSelection.Designer.cs +++ b/Duplicati/GUI/HelperControls/TestSearchSelection.Designer.cs @@ -138,14 +138,16 @@ namespace Duplicati.GUI.HelperControls { // this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream"))); this.imageList.TransparentColor = System.Drawing.Color.Transparent; - this.imageList.Images.SetKeyName(0, "Inclusion.ico"); - this.imageList.Images.SetKeyName(1, "Exclusion.ico"); + this.imageList.Images.SetKeyName(0, "globbing-include"); + this.imageList.Images.SetKeyName(1, "globbing-exclude"); this.imageList.Images.SetKeyName(2, "icon_up_sort_arrow[1].png"); this.imageList.Images.SetKeyName(3, "icon_down_sort_arrow[1].png"); this.imageList.Images.SetKeyName(4, "sort_ascending[1].png"); this.imageList.Images.SetKeyName(5, "sort_descending[1].png"); this.imageList.Images.SetKeyName(6, "sort_up[1].png"); this.imageList.Images.SetKeyName(7, "sort_down[1].png"); + this.imageList.Images.SetKeyName(8, "regexp-include"); + this.imageList.Images.SetKeyName(9, "regexp-exclude"); // // label1 // diff --git a/Duplicati/GUI/HelperControls/TestSearchSelection.cs b/Duplicati/GUI/HelperControls/TestSearchSelection.cs index 22732ec98..185a8cfbb 100644 --- a/Duplicati/GUI/HelperControls/TestSearchSelection.cs +++ b/Duplicati/GUI/HelperControls/TestSearchSelection.cs @@ -94,11 +94,26 @@ namespace Duplicati.GUI.HelperControls { bool sortingOrderAsc = true; private string[] m_paths; - private List> m_filters; private string m_dynamicFilters; public string[] Paths { get { return m_paths; } set { m_paths = value; } } - public List> Filters { get { return m_filters; } set { m_filters = value; } } + public List Filters + { + get + { + List filters = new List(); + foreach (ListViewItem lvi in lvFilters.Items) + filters.Add((FilterDialog.FilterEntry)lvi.Tag); + + return filters; + } + set + { + lvFilters.Items.Clear(); + foreach (FilterDialog.FilterEntry fe in value) + lvFilters.Items.Add(fe.CreateListViewItem()); + } + } public string DynamicFilters { get { return m_dynamicFilters; } set { m_dynamicFilters = value; } } List _results = new List(); @@ -116,9 +131,6 @@ namespace Duplicati.GUI.HelperControls { currentSortingColumn = 2; lvFiles.Columns[currentSortingColumn].ImageIndex = SORT_ASC_IMAGEINDEX + ( sortingOrderAsc ? 0 : 1 ); - foreach (KeyValuePair f in Filters) - lvFilters.Items.Add(new ListViewItem(f.Value, f.Key ? 0 : 1)); - StartScanThread(); } @@ -194,9 +206,12 @@ namespace Duplicati.GUI.HelperControls { } } - private void DoTestSearchSelection() { + private List DoTestSearchSelection(List filters) { + + List> dyn_filters = new List>(); + foreach (FilterDialog.FilterEntry fe in filters) + dyn_filters.Add(new KeyValuePair(fe.Include, fe.Filter)); - List> dyn_filters = new List>(Filters); if (!string.IsNullOrEmpty(DynamicFilters)) dyn_filters.AddRange(Library.Utility.FilenameFilter.DecodeFilter(DynamicFilters)); @@ -204,30 +219,46 @@ namespace Duplicati.GUI.HelperControls { try { + CallbackHandler handler = new CallbackHandler(scanWorker); foreach (string scanDir in Paths) { if (!scanWorker.CancellationPending) - Library.Utility.Utility.EnumerateFileSystemEntries(scanDir, fn, AddFileToList_Callback); + Library.Utility.Utility.EnumerateFileSystemEntries(scanDir, fn, handler.AddFileToList_Callback); } + + return handler.Results; } catch (AbortException) { + return null; } } - void AddFileToList_Callback(string rootpath, string path, Duplicati.Library.Utility.Utility.EnumeratedFileStatus status) + + private class CallbackHandler { + public List Results = new List(); + private BackgroundWorker Worker; - if (scanWorker.CancellationPending) - throw new AbortException(); - - if (status == Utility.EnumeratedFileStatus.File) + public CallbackHandler(BackgroundWorker worker) { - _results.Add(new ResultItem(path)); + Worker = worker; } - else if (status == Utility.EnumeratedFileStatus.Folder) + + public void AddFileToList_Callback(string rootpath, string path, Duplicati.Library.Utility.Utility.EnumeratedFileStatus status) { - //Should be displayed in tree so the user can exclude with right click? + + if (Worker.CancellationPending) + throw new AbortException(); + + if (status == Utility.EnumeratedFileStatus.File) + { + Results.Add(new ResultItem(path)); + } + else if (status == Utility.EnumeratedFileStatus.Folder) + { + //Should be displayed in tree so the user can exclude with right click? + } } } @@ -291,34 +322,18 @@ namespace Duplicati.GUI.HelperControls { lvFiles.Invalidate(); } - bool ExtractLastDirectory(StringBuilder path, StringBuilder dest) { - if( path.Length == 0 ) - return false; - - int i = path.Length; - - while( --i > -1 ) { - if( path[i] == '\\' ) { - if( i != path.Length - 1 && i > 3 ) - break; - else continue; - } - - dest.Insert(0, path[i]); - } - i = i > -1 ? i : 0; - - path.Remove(i, path.Length - i); - - return true; - } void AddFilter(bool include, string filter) { - Filters.Add(new KeyValuePair(include, filter)); - lvFilters.Items.Add(filter, include ? 0 : 1); + FilterDialog.FilterEntry fe = new FilterDialog.FilterEntry(include, FilenameFilter.ConvertGlobbingToRegExp(filter), filter); + lvFilters.Items.Add(fe.CreateListViewItem()); } + string GetFileFilterStr(string filename, string ext) { - return string.Format(@".*\\{0}.{1}", filename, ext); + if (filename == "*") + return string.Format("*.{0}", ext); + else + return string.Format("*\\{0}.{1}", filename, ext); } + void _AddSelectedFilter(bool include, bool anyFileName) { if( lvFiles.SelectedIndices.Count > 0 ) { foreach( int index in lvFiles.SelectedIndices ) { @@ -343,7 +358,7 @@ namespace Duplicati.GUI.HelperControls { _AddSelectedFilter(false, true); } - // Exlude File Path + // Exclude File Path private void ctxSelection_Opened(object sender, EventArgs e) { if( lvFiles.SelectedIndices.Count > 0 ) { ResultItem itm = GetResultItem(lvFiles.SelectedIndices[0]); @@ -356,17 +371,38 @@ namespace Duplicati.GUI.HelperControls { miExcludeFileExt.Text = fileExt; // Add Path items - StringBuilder completePath = new StringBuilder(itm.Path); - StringBuilder path = new StringBuilder(completePath.Length ); miExludeFilePath.DropDownItems.Clear(); + miIncludeFilePath.DropDownItems.Clear(); - while( ExtractLastDirectory(completePath, path) ) { - string s = ( completePath.Length > 0 ) ? string.Format(@".*\\{0}\\", path) : path.ToString(); - - miIncludeFilePath.DropDownItems.Add(s, null, FilterFilePath_Click).Tag = true; - miExludeFilePath.DropDownItems.Add(s, null, FilterFilePath_Click).Tag = false; + string fullpath = Utility.AppendDirSeparator(itm.Path); + string root = System.IO.Path.GetPathRoot(fullpath); + string curpath = System.IO.Path.GetDirectoryName(fullpath); + List folderlist = new List(); - path.Insert(0, @"\\"); + do + { + if (curpath != System.IO.Path.GetDirectoryName(curpath)) + folderlist.Add(Utility.AppendDirSeparator(curpath)); + curpath = System.IO.Path.GetDirectoryName(curpath); + } while (root != curpath); + + folderlist.Add(root); + + foreach (string s in folderlist) + { + if (s.Length >= fullpath.Length) + continue; + + string filter = string.Format(@"*\{0}", fullpath.Substring(s.Length)); + miIncludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = true; + miExludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = false; + } + + foreach (string s in folderlist) + { + string filter = string.Format(@"{0}", s); + miIncludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = true; + miExludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = false; } } @@ -388,24 +424,26 @@ namespace Duplicati.GUI.HelperControls { tbSearch.Enabled = false; lvFiles.Enabled = false; lvFilters.Enabled = false; - scanWorker.RunWorkerAsync(); + scanWorker.RunWorkerAsync(this.Filters); } private void scanWorker_DoWork(object sender, DoWorkEventArgs e) { //if( _results.Count == 0 ) - DoTestSearchSelection(); + e.Result = DoTestSearchSelection((List)e.Argument); //else UpdateSearchSelection(); if (scanWorker.CancellationPending) e.Cancel = true; } private void scanWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { - if (e.Error == null && !e.Cancelled) + if (e.Error == null && !e.Cancelled && e.Result as List != null) { lbLoading.Visible = false; tbSearch.Enabled = true; lvFiles.Enabled = true; lvFilters.Enabled = true; + _results = (List)e.Result; + LoadFileView(); SortView((ResultItemSortBy)currentSortingColumn, true); } @@ -442,7 +480,6 @@ namespace Duplicati.GUI.HelperControls { if( lvFilters.SelectedItems.Count > 0 ) { for(int i = lvFilters.SelectedItems.Count-1; i > -1; i--) { - Filters.RemoveAt(lvFilters.SelectedItems[i].Index); lvFilters.Items.RemoveAt(lvFilters.SelectedItems[i].Index); } @@ -493,8 +530,5 @@ namespace Duplicati.GUI.HelperControls { { this.DialogResult = DialogResult.OK; } - - - } } diff --git a/Duplicati/GUI/HelperControls/TestSearchSelection.resx b/Duplicati/GUI/HelperControls/TestSearchSelection.resx index 02ed0d4dd..7cce4a192 100644 --- a/Duplicati/GUI/HelperControls/TestSearchSelection.resx +++ b/Duplicati/GUI/HelperControls/TestSearchSelection.resx @@ -127,104 +127,134 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAB+ - FgAAAk1TRnQBSQFMAgEBCAEAAawBAAGsAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA - AwABMAMAAQEBAAEgBgABMP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AKQABAQMhATADIwEz - AyMBMwMhATAMAAMfASwDIwEzAyMBMwMjATMDIwEzAyMBMwMhATAMAAMjATMDIwEzEAADHwEsAyMBMwMj - ATMDIQEwWwAEAQECAwMBBAMFBAcBCQMGAQgDBAEGAwMBBAMBAQIDAAEBEAADAgEDAYsBcAFTAfEBtwGD - ATwB/wG3AYMBPQH/AYwBcgFNAfIMAAFbAWUBWwHhAUIBhQFEAf8BQwGEAUMB/wFDAYQBQwH/AUQBhAFE - Af8BRAGFAUYB/wFWAXUBWQHyCAADIwEzAbcBgwE9Af8BtwGDAT0B/wMjATMMAAFbAWUBWwHhAUIBhQFF - Af8BQwGFAUUB/wFWAXUBWQHyXAADBAEFAwkBDAMNAREDMQFOAxoBJAMPARQDDQERAwkBDAMEAQUUAAG3 - AYIBPAH/AfsBzgGIAf8B+QHKAYAB/wG5AYMBPAH/DAABQQGEAUQB/wGeAegByQH/AUkByAGSAf8BSwHI - AZMB/wFMAcgBlAH/AU4BzAGZAf8BQwGFAUUB/wQAAyMBMwG1AYEBOgH/AfQBxAFzAf8B9AHEAXMB/wG1 - AYEBOgH/AyMBMwgAAUABhAFEAf8BngHpAcoB/wFMAcwBmAH/AUMBhQFFAf9kAAM3AVsDlgH0A1wBxQMB - AQIgAAG2AYEBOgH/AfQBywGKAf8B8QHAAW4B/wG4AYIBOwH/DAABQAGEAUMB/wG7AeoB3QH/AbgB5gHY - Af8BuQHmAdgB/wG6AecB2QH/Ab0B6wHeAf8BQQGFAUQB/wMjATMBtQGBAToB/wHyAcEBbwH/Ae4BvAFr - Af8B7gG9AWwB/wHyAcEBbwH/AbgBgQE6Af8DIwEzBAABPgGEAUMB/wG8AesB3gH/Ab0B6wHfAf8BQQGF - AUQB/2AAAxYBHgFvAXABbwHiAbwBwwHAAf8BrQGzAbEB+wNMAZAgAAG2AYEBOgH/AfEBygGQAf8B6wG4 - AWYB/wG4AYIBOwH/DAADVAGuAUABhAFDAf8BPgGCAUAB/wE+AYIBQAH/AT4BggFAAf8BQAGEAUMB/wFX - AVoBVwHFAbgBhAE9Af8B9wHOAY8B/wHyAckBiQH/Ae0BwgGCAf8B6wG5AWgB/wHyAckBigH/AfkBzgGP - Af8BwgGEATwB/wQAAVQBVgFUAasBQAGEAUMB/wFAAYQBQwH/AVYBWAFWAcFcAAMDAQQDXQHKAcMByQHG - Af8BtgG9AboB/wG6AcEBvgH/AZABkgGQAfEDLgFIHAABtgGBATkB/wHvAc0BmAH/AeYBsgFfAf8BuAGC - ATwB/wwAAxkEIwEzAyMBMwMjATMDGAEiCAABXQFaAVcBxQG3AYIBOwH/AbMBdgE2Af8B8AHIAY4B/wHp - AbgBZQH/AbMBdwE4Af8BuAGCATsB/wJbAVkBxAQAAxkEIwEzAyMBMwMjATMDGQEjEwABAQMCAQMDBQEH - AwgECwEPAw0BEgMNARIDCgEOAwgBCwMFAQcDAgEDHAADUAGbAbYBuQG4AfwBtgG9AboB/wG7AcIBvwH/ - AccBzQHLAf8B1QHZAdcB/wN0AeQDDwEUGAABtgGBATkB/wHuAc8BoQH/AeABrAFXAf8BuQGDAT0B/wwA - AVYBWQFWAb4BQgGFAUQB/wFDAYQBQwH/AUQBhQFGAf8BVwFaAVcBvRAAAbYBgAE5Af8B8AHLAZYB/wHn - AbQBYgH/AbYBggE7Af8MAAFXAVoBVwG9AUEBhQFEAf8BQwGEAUMB/wFEAYUBRgH/AVcBWQFXAb8fAAEB - AwQBBQMGAQgDBgEIAwUBBwMCAQMgAAM1AVcBkAGSAZAB8QG5AcABvQH/Ab0BwwHAAf8BwwHIAcYB/wHH - Ac0BywH/Ac0B0gHQAf8B2wHeAd0B/wNcAccDAAEBFAABtgGBATgB/wHvAdMBqgH/AdoBpQFQAf8BuQGD - AT0B/wwAAUABhAFEAf8BngHoAckB/wFKAckBkwH/AU4BzAGYAf8BQwGFAUUB/xAAAbYBgQE5Af8B7wHO - AZ0B/wHkAbEBXQH/AbgBggE8Af8MAAE/AYUBRAH/AZ4B6AHJAf8BSgHJAZMB/wFOAcwBmAH/AUMBhQFF - Af8MAANIAYMBZgFnAWYB1QFmAmcB1QNlAdQDYgHTA2IB0wNhAdIDYwHRA2MB0QNjAdEDYwHRA2EB0gNg - AdEDEgEZDAADFAEbAW4CcQHgAb4BxAHBAf8BtwG+AbsB/wG7AcIBvwH/AcABxgHEAf8BxQHLAckB/wHL - AdABzQH/AdAB1AHSAf8BwgHFAcQB/ANKAY0UAAG2AYEBOAH/AfAB2QG0Af8B1gGfAUkB/wG4AYQBPQH/ - DAABPgGEAUMB/wG7AeoB3QH/AbkB5wHZAf8BvQHrAd4B/wFBAYUBRAH/EAABtgGBATgB/wHwAdEBpAH/ - AeABrAFXAf8BuAGDATwB/wwAAUABhAFDAf8BuwHqAd0B/wG5AecB2QH/Ab0B6wHeAf8BQQGFAUQB/wwA - Ax0BKQOJAe4B2wHeAd0B/wHSAdcB1QH/Ac4B0wHRAf8ByQHOAcwB/wHFAcoByAH/AcABxgHDAf8BvQHD - AcEB/wG9AcMBwQH/Ab0BwwHBAf8BzAHRAc8B/wNYAbcMAAMCAQMDXgHJAcUBygHIAf8BtwG+AbsB/wG3 - Ab4BuwH/AbkBwAG9Af8BvgHFAcIB/wHDAckBxgH/AckBzgHMAf8BzQHSAdAB/wHVAdkB1wH/A5oB8wMs - AUMIAAMhATADIwEzAbcBgQE4Af8B7wHbAb0B/wHQAZoBQgH/AbgBhAE+Af8DIwEzAyEBMAQAAVMBVQFT - Aa0BPwGEAUMB/wE+AYIBQQH/AUABhAFDAf8BVAFuAVQB7hAAAbYBgQE4Af8B7wHUAa0B/wHdAagBUwH/ - AbkBgwE9Af8MAANUAa4BQAGEAUMB/wE+AYIBQQH/AUABhAFDAf8BWAFuAVkB6xAAAz8BbAG1ArgB+gHS - AdYB1AH/AcwB0QHPAf8BxwHMAcoB/wHCAcgBxQH/Ab0BwwHAAf8BtwG+AbsB/wG3Ab4BuwH/AcEBxwHF - Af8DaAHaAwoBDgwAA0wBkwG3AbsBuQH8AcUBywHIAf8BxQHLAcgB/wHFAcsByAH/AcUBywHIAf8ByAHO - AcsB/wHMAdEBzgH/Ac8B1AHSAf8B0wHXAdUB/wHWAdoB2AH/Ad8B4gHhAf8DbwHiAwMBBAQAAYsBcgFN - AfIBuQGEATwB/wG3AYEBOQH/AdoBtwGHAf8BxgGPAT4B/wG4AYMBPQH/AboBhAE8Af8BkAFwAVMB8QQA - AxgBIgMjATMDIwEzAxgBIhQAAbYBgQE4Af8B8AHYAbUB/wHZAaMBTQH/AbkBgwE9Af8MAAMZBCMBMwMj - ATMDIwEzAyMBMwMjATMDGQEjDAADVAGuAc4B0gHQAf4BzgHTAdEB/wHJAc4BzAH/AcQBygHHAf8BvwHF - AcIB/wG6AcABvgH/AboBwQG+Af8DgwHtAygBPBAAAyABLgM/AWwDPwFsAz8BbAM+AWsDPgFqAz4BagM+ - AWoDPQFpAz0BaQM9AWgDPQFoAzsBZAMEAQYEAAG5AYQBPQH/AegB0QGsAf8BxgGPATcB/wHGAY8BOQH/ - AcYBkAE6Af8BxgGPATcB/wHsAdUBsgH/AcMBhAE7Af8EAAFWAVgBVgG8AUIBhQFFAf8BQwGFAUUB/wFX - AVoBVwG9FAABtgGAATcB/wHxAdwBvAH/AdUBnwFIAf8BuQGEAT0B/wwAAVYBWQFWAb4BQgGFAUQB/wFD - AYQBQwH/AUMBhAFDAf8BRAGEAUQB/wFEAYUBRgH/AVgBWgFYAcAMAAMFAQcDZQLZAdwB2wH/AcsB0AHO - Af8BxgHLAckB/wG9AcQBwQH/AbgBvwG8Af8BqQGsAasB+gNIAYNUAAG4AYIBOQH/AegB0AGtAf8BwgGL - ATEB/wHCAYsBMQH/AegB0AGtAf8BuQGCATkB/wgAAT8BhQFEAf8BngHpAcoB/wFMAcwBmAH/AUMBhQFF - Af8UAAG3AYEBNwH/AfAB2wG7Af8B0AGZAUEB/wG6AYMBPAH/DAABQQGEAUQB/wGeAegByQH/AUkByAGS - Af8BSwHIAZMB/wFMAcgBlAH/AU4BzAGZAf8BQwGFAUUB/xAAAxwBJwGDAYQBgwHrAcsB0AHOAf8BuQHA - Ab0B/wG2Ab0BugH/AcUBygHIAf8DWQG/XAABtwGBATkB/wHoAdEBsAH/AegB0QGwAf8BuAGBATkB/wwA - AT8BhAFDAf8BvAHrAd4B/wG9AesB3wH/AUEBhQFEAf8UAAG4AYIBOQH/Ae8B2wG7Af8B6gHQAakB/wG6 - AYMBOwH/DAABQAGEAUMB/wG7AeoB3QH/AbgB5gHYAf8BuQHmAdgB/wG6AecB2QH/Ab0B6wHeAf8BQQGF - AUQB/xQAAz0BaAGXAZsBmQH1AbcBvgG7Af8BvgHFAcIB/wNpAd4DDQESYAABuAGDATsB/wG4AYMBOwH/ - EAABUwFVAVMBsAFAAYQBQwH/AUABhAFDAf8BVQFuAVgB7xQAAlUBUwGwAbgBggE6Af8BuAGDAToB/wJV - AVMBsAwAAVMBVQFTAbABQAGEAUMB/wE+AYIBQAH/AT4BggFAAf8BPgGCAUAB/wFAAYQBQwH/AVUBbgFY - Ae8YAANSAakBuwHAAb4B/gGGAYcBhgHvAy0BRvAAAwUBBwNbAcQDRgF+/wB1AAMTARoBLAIrAUMBLAIr - AUMBLAIrAUPwAANVAbIBRAHiAYwB/wFDAeEBiQH/ATUByAFdAf/wAANVAbIBOAHUAVgB/wEvAcsBPwH/ - ATUByQFdAf+wAAMMARADPQFoAyoBQDQAA1UBsgFAAdoBYgH/ATABzAFBAf8BNQHKAV0B/1wAAxABFgMX - ASADFwEgAxcBIAMXASADFwEgAxcBIAMXASADFwEgAxcBIAMXASADFwEgAxcBIAMJAQwYAAMKAQ4DKAE8 - A14B1QNMAZADEwEaAwMBBCwAA1UBsgFMAeMBgQH/ATwB1AFOAf8BNgHLAV4B/1wAA0gBgwNZAb8DWQG/ - A1kBvwNZAb8DWQG/A1kBvwNZAb8DWQG/A1kBvwNZAb8DWQG/A1kBvwMuAUgYAAM0AVQDWQHHA18B8wNd - Ad8DUAGbAxIBGBwAAT4BfwE8Af4BPwHTAWQB/wE/AdQBZgH/AUAB1AFmAf8BPwHTAWUB/wFYAeoBhAH/ - AUsB3wFeAf8BSQHjAZAB/wE2AcoBXAH/ATQByAFbAf8BMwHGAVkB/wEzAcUBWQH/AzABTAwAA0gBhAI7 - AdMB/wI9AdQB/wI/AdQB/wJAAdMB/wI/AdAB/wI8AcwB/wI4AccB/wI0AcMB/wIyAcIB/wIyAcIB/wIh - AagB/wwAAz8BbQNbAcMDXwH/A18B/wNfAf8DXwH/A18B/wNfAf8DXwH/A18B/wNfAf8DZAHnA1MBpQMo - ATwQAAMEAQYDLgFIA1QBpgNfAf8DXwH/A18B/wNhAeEDQgF0Ax0BKhgAAUEBgwFBAf4BVAHaAWcB/wFd - AeQBgQH/AWMB7AGGAf8BZgHwAYoB/wFjAe8BhwH/AVoB6gGBAf8BTQHhAWEB/wFAAdcBUgH/ATQBzgFF - Af8BLwHLAT8B/wFCAeABhwH/AzABTAwAA0gBhAJNAdcB/wJUAdYB/wJgAeQB/wJoAe4B/wJoAfAB/wJc - AekB/wJJAdwB/wI5AdAB/wI0AcwB/wI0AcwB/wIrAbcB/xAAAzoBYANfAf8DXwH/A18B/wNfAf8DXwH/ - A18B/wNfAf8DXwH/A18B/wNZAb8DDAEQFAADDAEQA1kBvwNfAf8DXwH/A18B/wNfAf8DXwH/A18B/wNA - AXAYAAFBAYQBQQH+AU0B1gGBAf8BVQHfAYUB/wFcAecBjQH/AWEB7gGTAf8BZgHvAYoB/wFkAfABiAH/ - AVwB7AGGAf8BUQHnAYIB/wFGAd4BaAH/ATwB1wFdAf8BQwHhAYoB/wMwAUwMAANIAYQCTgHaAf8CVQHd - Af8CXwHoAf8CZQHwAf8CZQHyAf8CXAHsAf8CTQHiAf8CPwHYAf8COgHUAf8COgHUAf8CKwG3Af8QAAMa - ASQDPgFqA10B1wNfAf8DXwH/A18B/wNfAf8DXwH/A18B/wNUAaYDLgFIAwQBBhAAAygBPANTAaUDZAHn - A18B/wNfAf8DXwH/A18B/wNfAf8DXwH/A1wByQNDAXcDBwEKEAABVgJVAbEDVQG1A1UBtQNVAbUDVwHo - AWEB7QGTAf8BZgHvAYkB/wFCAdYBgQH/A1UBtQNVAbUDVQG1A1UBtQMYASEMAAMtAUYDVQG1A1UBtQNV - AbUDVQG1A1UBtQNVAbUDVQG1A1UBtQNVAbUDVQG1AVYCVQG0FAADCQEMA0wBjwNfAdsDXwH/A18B/wNf - Af8DXwHzA1kBxwM0AVQUAAMfASwDSQGIA18B/wNfAf8DXwH/A18B/wNfAf8DXwH/A18B/wNfAf8DXwH/ - A1wBzwMwAUwDEgEYHAADVQGyAVoB5QGLAf8BYQHoAYMB/wFCAdYBgQH/ZAADAQECAxIBGANHAYIDXwH/ - A18B/wNfAf8DXgHVAygBPAMKAQ4UAANOAZkDYAHrA18B/wNfAf8DXwH/A18B/wNfAf8DXwH/A18B/wNf - Af8DXwH/A2YB9wNhAeEDNAFUHAADVQGyAVEB2wGBAf8BWAHeAYAB/wFBAdUBagH/bAADJgE4A0wBkANk - AecDWgHAAz0BaAMMARAYAAM2AVgDRwGAA0cBgANHAYADRwGAA0cBgANHAYADRwGAA0cBgANHAYADRwGA - A0cBgANHAYADIQEwHAADVQGyAUgB0gFpAf8BTQHTAWAB/wFAAdQBaAH/cAADFAEcA1UBtQNAAXB0AANU - AasBIwG5ASgB/wEjAbgBKAH/ASEBtQEkAf9wAAMGAQgDIwE0AxcBIP8A/wBeAAFCAU0BPgcAAT4DAAEo - AwABQAMAATADAAEBAQABAQUAAYABARYAA/+BAAGDAYAB5wGHAv8B4AEHAYMBgAHDAYcC/wHwAQcBwwGA - AYEBhwL/AfwBPwHDAYABAAGHAv8B+AE/AcMBgAEAAYcC/wHwAR8BwwGDAQABgwHAAQcB8AEPAcMBgwHD - AYMB+AEfAeABBwHDAYMBwwGDAYABAQHAAQcBwwGDAcMBgwGAAQMBgAEDAQABgwHDAYMBwAEDAYABAQEA - AYcBwwGAAeABBwGAAQEBAAGHAcMBgAHgAQ8C/wGBAYcBwwGAAfABHwL/AcMBhwHDAYAB+AEfAv8B5wGH - AcMBgAH8AT8G/wH8AX8K/wH8AT8G/wH8AT8G/wH8AT8E/wH8AX8B/AE/Av8BgAEBAfgBHwH8AT8C/wGA - AQEB+AEfAcABAQHAAQMBgAEBAeABDwHAAQEBwAEDAcABAwHgAQ8BwAEBAcABAwHAAQMBwAEDAcABAQHA - AQMB4AEPAYABAQH8AT8C/wHgAQ8BgAEBAfwBPwL/AfgBHwGAAQEB/AE/Av8B/AF/Av8B/AE/Av8B/AF/ - Ev8L + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACy + HQAAAk1TRnQBSQFMAgEBCgEAAbQBAAG0AQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABMAMAAQEBAAEgBgABMP8A/wD/ABkAASgBpAEoAf8BKAGkASgB/wwAAS0BmgEuAfYBKAGkASgB/wEq + AaIBKwH9ASgBpAEoAf8BIgEmASIBMQgAAwgBCwEoAaQBKAH/ASgBpAEoAf8EAAIoAaQB/wIoAaQB/wwA + Ai0BnQH2AigBpAH/AioBowH9AigBpAH/AiIBJgExCAACCAEJAQsCKAGkAf8CKAGkAf+EAAFCAcgBZQH/ + AU0B2AF+Af8IAAEmASsBJgE4AUYB0QFpAf8BPgHFAVcB/wEvAZYBMwHuAU0B3AF4Af8BKgGnAS0B/wgA + ASoBogErAf0BWwHrAZ8B/wEoAaQBKAH/BAACSgHIAf8CWwHaAf8IAAImASsBOAJQAdMB/wJFAcYB/wEv + ATEBmAHuAlkB3QH/AisBpwH/CAACKgGjAf0CbQHsAf8CKQGiAf6EAAFBAccBYgH/AUwB1gF5Af8IAAEo + AaQBKAH/AUoB2QFxAf8BMAGYATMB8QQAAS0BrAE0Af8BSwHaAXMB/wE6AYcBPQHOAUABYQFEAYwBUgHg + AYgB/wE8AcABVgH/AQwBDQEMARAEAAJKAcgB/wJaAdgB/wgAAigBpAH/AVUBVAHaAf8BMAExAZoB8QQA + Ai8BrQH/AlcB3AH/AToBPQGIAc4BQAFCAWEBjAJiAeMB/wJEAcIB/wIMAQ0BEIQAAUEBxgFhAf8BSwHV + AXcB/wEpATEBKQI/AXQBRQGvAUYB0gFoAf8BOgHAAU0B/wEOAQ8BDgETBAABNQFCATcBWgFBAcwBXgH/ + AT0BxQFWAf8BNQG3AUUB/wFSAeABhwH/AUEBbQFFAaEIAAJKAcgB/wJYAdcB/wIpATECPwFCAXYBrwJP + AdQB/wI/AcIB/wIOAQ8BEwQAATUBNgFDAVoCSgHOAf8CRQHHAf8COgG4Af8CYgHjAf8BQQFEAW8BoYgA + AUABxgFgAf8BVQHlAY8B/wFRAeABhAH/AU0B3AF4Af8BQwHOAWAB/wE0AZMBNwHmDAABMgGWATUB6wFL + AdkBcgH/AU8B3gF9Af8BKAGkASgB/wwAAkoBxwH/AmcB5wH/AmAB4gH/AlkB3gH/AUwBSwHQAf8BNAE2 + AZQB5gwAATIBNQGXAesCVwHbAf8CXQHgAf8CKAGkAf+MAAFAAcYBYAH/AUoB1QF1Af8BKAGkASgB/wEo + AaUBKQH/AUcB1QFpAf8BOAG/AUoB/wMJAQwIAAE/AVwBRAGFAUcB1AFqAf8BTwHeAXwB/wEtAZ4BLwH3 + DAACSgHHAf8CVwHWAf8CKAGkAf8CKQGlAf8BUgFRAdcB/wI+AcEB/wMJAQwIAAE/AUEBXgGFAlIB1gH/ + Al0B4AH/AS0BLgGfAfeMAAFBAcYBYAH/AUoB1QF2Af8IAAExAbMBPAH/AUYB1QFmAf8BNgFGATgBXwQA + AwQBBgExAbMBPAH/AUoB2AFwAf8BOwHBAVMB/wFOAdsBfQH/AT0BVgFBAXkIAAJKAcgB/wJYAdcB/wgA + AjUBtAH/AlAB1wH/ATYBNwFHAV8EAAMEAQYCNQG0Af8CVwHbAf8CQwHDAf8CXQHeAf8BPQFAAVcBeYgA + AUEBxwFiAf8BSwHWAXgB/wFBAXEBQQGfAToBhgFAAdABQwHOAWMB/wFGAdMBZwH/ASYBKwEmATgEAAEp + AZ0BKwH7AUoB2QFxAf8BKAGkASgB/wE/AXgBRAG0AVQB4wGMAf8BNQG2AUUB/wMDAQQEAAJKAcgB/wJa + AdgB/wJBAXEBnwE6AT4BiQHQAk4B0AH/AlEB1QH/AiYBKwE4BAABKQEqAZ4B+wJXAdwB/wIoAaQB/wE/ + AUIBegG0AmYB5gH/AjoBtwH/AwMBBIQAAUIByAFkAf8BWQHpAZkB/wFVAeUBjwH/AVIB4QGGAf8BTgHc + AXsB/wEpAaABKgH+BAABPwFdAUMBhAFIAdYBbgH/ATgBvAFLAf8BDgEPAQ4BEwQAASgBpQEpAf8BWwHq + AZ0B/wEqAZ0BKwH5BAACSgHIAf8CbAHrAf8CaAHoAf8CYwHkAf8CXQHgAf8CKQGiAf4EAAE/AUEBXgGE + AlUB2QH/Aj8BvgH/Ag4BDwETBAACKQGlAf8CbQHsAf8BKgErAZ4B+YQAAT4BgQE+AbsBPgGEAT4BvwE+ + AYQBPgG/AT4BfAFDAbsBOAFKAToBZQgAATEBPQEzAVEBPgGCAT4BvwE9AVYBQAF4CAABEQESAREBFwE+ + AYIBPgG/AUEBdgFCAawEAAI+AYEBuwI+AYQBvwI+AYQBvwE+AUABfwG7ATgBOQFKAWUIAAExATIBPQFR + Aj4BggG/AT0BPwFXAXgIAAIRARIBFwI+AYIBvwJBAXgBrP8A/wD/AIoAAQEDIQEwAyMBMwMjATMDIQEw + DAADHwEsAyMBMwMjATMDIwEzAyMBMwMjATMDIQEwDAADIwEzAyMBMxAAAx8BLAMjATMDIwEzAyEBMFsA + BAEBAgMDAQQDBQQHAQkDBgEIAwQBBgMDAQQDAQECAwABARAAAwIBAwGGAW8BUwHxAbcBgwE7Af8BtwGD + ATwB/wGJAW8BTgHyDAABWwFjAVsB4QFBAYUBQwH/AUIBhAFCAf8BQgGEAUIB/wFDAYQBQwH/AUMBhQFF + Af8BVwFyAVkB8ggAAyMBMwG3AYMBPAH/AbcBgwE8Af8DIwEzDAABWwFjAVsB4QFBAYUBRAH/AUIBhQFE + Af8BVwFyAVkB8lwAAwQBBQMJAQwDDQERAzEBTgMaASQDDwEUAw0BEQMJAQwDBAEFFAABtwGCATsB/wH7 + Ac4BiAH/AfkBygGAAf8BuQGDATsB/wwAAUABhAFDAf8BngHoAckB/wFIAcgBkgH/AUoByAGTAf8BSwHI + AZQB/wFNAcwBmQH/AUIBhQFEAf8EAAMjATMBtQGBATkB/wH0AcQBcgH/AfQBxAFyAf8BtQGBATkB/wMj + ATMIAAE/AYQBQwH/AZ4B6QHKAf8BSwHMAZgB/wFCAYUBRAH/ZAADNwFbA5IB9ANaAcUDAQECIAABtgGB + ATkB/wH0AcsBigH/AfEBwAFtAf8BuAGCAToB/wwAAT8BhAFCAf8BuwHqAd0B/wG4AeYB2AH/AbkB5gHY + Af8BugHnAdkB/wG9AesB3gH/AUABhQFDAf8DIwEzAbUBgQE5Af8B8gHBAW4B/wHuAbwBagH/Ae4BvQFr + Af8B8gHBAW4B/wG4AYEBOQH/AyMBMwQAAT0BhAFCAf8BvAHrAd4B/wG9AesB3wH/AUABhQFDAf9gAAMW + AR4BagFrAWoB4gG8AcMBwAH/AakBrwGtAfsDTAGQIAABtgGBATkB/wHxAcoBkAH/AesBuAFlAf8BuAGC + AToB/wwAA1QBrgE/AYQBQgH/AT0BggE/Af8BPQGCAT8B/wE9AYIBPwH/AT8BhAFCAf8BVwFaAVcBxQG4 + AYQBPAH/AfcBzgGPAf8B8gHJAYkB/wHtAcIBggH/AesBuQFnAf8B8gHJAYoB/wH5Ac4BjwH/AcIBhAE7 + Af8EAAFUAVYBVAGrAT8BhAFCAf8BPwGEAUIB/wFWAVgBVgHBXAADAwEEA10BygHDAckBxgH/AbYBvQG6 + Af8BugHBAb4B/wGLAY4BiwHxAy4BSBwAAbYBgQE4Af8B7wHNAZgB/wHmAbIBXgH/AbgBggE7Af8MAAMZ + BCMBMwMjATMDIwEzAxgBIggAAVwBWgFXAcUBtwGCAToB/wGzAXUBNQH/AfAByAGOAf8B6QG4AWQB/wGz + AXYBNwH/AbgBggE6Af8CWwFZAcQEAAMZBCMBMwMjATMDIwEzAxkBIxMAAQEDAgEDAwUBBwMIBAsBDwMN + ARIDDQESAwoBDgMIAQsDBQEHAwIBAxwAA1ABmwG0AbcBtgH8AbYBvQG6Af8BuwHCAb8B/wHHAc0BywH/ + AdUB2QHXAf8DcAHkAw8BFBgAAbYBgQE4Af8B7gHPAaEB/wHgAawBVgH/AbkBgwE8Af8MAAFWAVkBVgG+ + AUEBhQFDAf8BQgGEAUIB/wFDAYUBRQH/AVcBWgFXAb0QAAG2AYABOAH/AfABywGWAf8B5wG0AWEB/wG2 + AYIBOgH/DAABVwFaAVcBvQFAAYUBQwH/AUIBhAFCAf8BQwGFAUUB/wFXAVkBVwG/HwABAQMEAQUDBgEI + AwYBCAMFAQcDAgEDIAADNQFXAYsBjgGLAfEBuQHAAb0B/wG9AcMBwAH/AcMByAHGAf8BxwHNAcsB/wHN + AdIB0AH/AdsB3gHdAf8DWwHHAwABARQAAbYBgQE3Af8B7wHTAaoB/wHaAaUBTwH/AbkBgwE8Af8MAAE/ + AYQBQwH/AZ4B6AHJAf8BSQHJAZMB/wFNAcwBmAH/AUIBhQFEAf8QAAG2AYEBOAH/Ae8BzgGdAf8B5AGx + AVwB/wG4AYIBOwH/DAABPgGFAUMB/wGeAegByQH/AUkByQGTAf8BTQHMAZgB/wFCAYUBRAH/DAADSAGD + A2MB1QNjAdUDYwHUA18B0wNfAdMDXwHSA2AB0QNgAdEDYAHRA2AB0QNfAdIDXwHRAxIBGQwAAxQBGwFr + AmwB4AG+AcQBwQH/AbcBvgG7Af8BuwHCAb8B/wHAAcYBxAH/AcUBywHJAf8BywHQAc0B/wHQAdQB0gH/ + Ab8BwgHBAfwDSgGNFAABtgGBATcB/wHwAdkBtAH/AdYBnwFIAf8BuAGEATwB/wwAAT0BhAFCAf8BuwHq + Ad0B/wG5AecB2QH/Ab0B6wHeAf8BQAGFAUMB/xAAAbYBgQE3Af8B8AHRAaQB/wHgAawBVgH/AbgBgwE7 + Af8MAAE/AYQBQgH/AbsB6gHdAf8BuQHnAdkB/wG9AesB3gH/AUABhQFDAf8MAAMdASkDhAHuAdsB3gHd + Af8B0gHXAdUB/wHOAdMB0QH/AckBzgHMAf8BxQHKAcgB/wHAAcYBwwH/Ab0BwwHBAf8BvQHDAcEB/wG9 + AcMBwQH/AcwB0QHPAf8DVwG3DAADAgEDA1wByQHFAcoByAH/AbcBvgG7Af8BtwG+AbsB/wG5AcABvQH/ + Ab4BxQHCAf8BwwHJAcYB/wHJAc4BzAH/Ac0B0gHQAf8B1QHZAdcB/wOVAfMDLAFDCAADIQEwAyMBMwG3 + AYEBNwH/Ae8B2wG9Af8B0AGaAUEB/wG4AYQBPQH/AyMBMwMhATAEAAFTAVUBUwGtAT4BhAFCAf8BPQGC + AUAB/wE/AYQBQgH/AVQBbAFUAe4QAAG2AYEBNwH/Ae8B1AGtAf8B3QGoAVIB/wG5AYMBPAH/DAADVAGu + AT8BhAFCAf8BPQGCAUAB/wE/AYQBQgH/AVkBawFZAesQAAM/AWwBsAKzAfoB0gHWAdQB/wHMAdEBzwH/ + AccBzAHKAf8BwgHIAcUB/wG9AcMBwAH/AbcBvgG7Af8BtwG+AbsB/wHBAccBxQH/A2YB2gMKAQ4MAANM + AZMBtQG5AbcB/AHFAcsByAH/AcUBywHIAf8BxQHLAcgB/wHFAcsByAH/AcgBzgHLAf8BzAHRAc4B/wHP + AdQB0gH/AdMB1wHVAf8B1gHaAdgB/wHfAeIB4QH/A2oB4gMDAQQEAAGIAW8BTgHyAbkBhAE7Af8BtwGB + ATgB/wHaAbcBhwH/AcYBjwE9Af8BuAGDATwB/wG6AYQBOwH/AYsBbwFTAfEEAAMYASIDIwEzAyMBMwMY + ASIUAAG2AYEBNwH/AfAB2AG1Af8B2QGjAUwB/wG5AYMBPAH/DAADGQQjATMDIwEzAyMBMwMjATMDIwEz + AxkBIwwAA1QBrgHMAdABzgH+Ac4B0wHRAf8ByQHOAcwB/wHEAcoBxwH/Ab8BxQHCAf8BugHAAb4B/wG6 + AcEBvgH/A38B7QMoATwQAAMgAS4DPwFsAz8BbAM/AWwDPgFrAz4BagM+AWoDPgFqAz0BaQM9AWkDPQFo + Az0BaAM7AWQDBAEGBAABuQGEATwB/wHoAdEBrAH/AcYBjwE2Af8BxgGPATgB/wHGAZABOQH/AcYBjwE2 + Af8B7AHVAbIB/wHDAYQBOgH/BAABVgFYAVYBvAFBAYUBRAH/AUIBhQFEAf8BVwFaAVcBvRQAAbYBgAE2 + Af8B8QHcAbwB/wHVAZ8BRwH/AbkBhAE8Af8MAAFWAVkBVgG+AUEBhQFDAf8BQgGEAUIB/wFCAYQBQgH/ + AUMBhAFDAf8BQwGFAUUB/wFYAVoBWAHADAADBQEHA2MC2QHcAdsB/wHLAdABzgH/AcYBywHJAf8BvQHE + AcEB/wG4Ab8BvAH/AaYBqQGoAfoDSAGDVAABuAGCATgB/wHoAdABrQH/AcIBiwEwAf8BwgGLATAB/wHo + AdABrQH/AbkBggE4Af8IAAE+AYUBQwH/AZ4B6QHKAf8BSwHMAZgB/wFCAYUBRAH/FAABtwGBATYB/wHw + AdsBuwH/AdABmQFAAf8BugGDATsB/wwAAUABhAFDAf8BngHoAckB/wFIAcgBkgH/AUoByAGTAf8BSwHI + AZQB/wFNAcwBmQH/AUIBhQFEAf8QAAMcAScBfwGAAX8B6wHLAdABzgH/AbkBwAG9Af8BtgG9AboB/wHF + AcoByAH/A1kBv1wAAbcBgQE4Af8B6AHRAbAB/wHoAdEBsAH/AbgBgQE4Af8MAAE+AYQBQgH/AbwB6wHe + Af8BvQHrAd8B/wFAAYUBQwH/FAABuAGCATgB/wHvAdsBuwH/AeoB0AGpAf8BugGDAToB/wwAAT8BhAFC + Af8BuwHqAd0B/wG4AeYB2AH/AbkB5gHYAf8BugHnAdkB/wG9AesB3gH/AUABhQFDAf8UAAM9AWgBkgGX + AZQB9QG3Ab4BuwH/Ab4BxQHCAf8DZgHeAw0BEmAAAbgBgwE6Af8BuAGDAToB/xAAAVMBVQFTAbABPwGE + AUIB/wE/AYQBQgH/AVYBawFYAe8UAAJVAVMBsAG4AYIBOQH/AbgBgwE5Af8CVQFTAbAMAAFTAVUBUwGw + AT8BhAFCAf8BPQGCAT8B/wE9AYIBPwH/AT0BggE/Af8BPwGEAUIB/wFWAWsBWAHvGAADUgGpAbkBvgG8 + Af4BggGDAYIB7wMtAUbwAAMFAQcDWwHEA0YBfv8AdQADEwEaASwCKwFDASwCKwFDASwCKwFD8AADVQGy + AUMB4gGMAf8BQgHhAYkB/wE0AcgBXAH/8AADVQGyATcB1AFXAf8BLgHLAT4B/wE0AckBXAH/sAADDAEQ + Az0BaAMqAUA0AANVAbIBPwHaAWEB/wEvAcwBQAH/ATQBygFcAf9cAAMQARYDFwEgAxcBIAMXASADFwEg + AxcBIAMXASADFwEgAxcBIAMXASADFwEgAxcBIAMXASADCQEMGAADCgEOAygBPANeAdUDTAGQAxMBGgMD + AQQsAANVAbIBSwHjAYEB/wE7AdQBTQH/ATUBywFdAf9cAANIAYMDWQG/A1kBvwNZAb8DWQG/A1kBvwNZ + Ab8DWQG/A1kBvwNZAb8DWQG/A1kBvwNZAb8DLgFIGAADNAFUA1kBxwNfAfMDXAHfA1ABmwMSARgcAAE+ + AX8BPAH+AT4B0wFjAf8BPgHUAWUB/wE/AdQBZQH/AT4B0wFkAf8BVwHqAYQB/wFKAd8BXQH/AUgB4wGQ + Af8BNQHKAVsB/wEzAcgBWgH/ATIBxgFYAf8BMgHFAVgB/wMwAUwMAANIAYQCOgHTAf8CPAHUAf8CPgHU + Af8CPwHTAf8CPgHQAf8COwHMAf8CNwHHAf8CMwHDAf8CMQHCAf8CMQHCAf8CIAGoAf8MAAM/AW0DWwHD + A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A2QB5wNTAaUDKAE8EAADBAEGAy4BSANU + AaYDXgH/A14B/wNeAf8DYQHhA0IBdAMdASoYAAFBAYEBQQH+AVMB2gFmAf8BXAHkAYEB/wFiAewBhgH/ + AWUB8AGKAf8BYgHvAYcB/wFZAeoBgQH/AUwB4QFgAf8BPwHXAVEB/wEzAc4BRAH/AS4BywE+Af8BQQHg + AYcB/wMwAUwMAANIAYQCTAHXAf8CUwHWAf8CXwHkAf8CZwHuAf8CZwHwAf8CWwHpAf8CSAHcAf8COAHQ + Af8CMwHMAf8CMwHMAf8CKgG3Af8QAAM6AWADXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNe + Af8DWQG/AwwBEBQAAwwBEANZAb8DXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DQAFwGAABQQGCAUEB/gFM + AdYBgQH/AVQB3wGFAf8BWwHnAY0B/wFgAe4BkwH/AWUB7wGKAf8BYwHwAYgB/wFbAewBhgH/AVAB5wGC + Af8BRQHeAWcB/wE7AdcBXAH/AUIB4QGKAf8DMAFMDAADSAGEAk0B2gH/AlQB3QH/Al4B6AH/AmQB8AH/ + AmQB8gH/AlsB7AH/AkwB4gH/Aj4B2AH/AjkB1AH/AjkB1AH/AioBtwH/EAADGgEkAz4BagNdAdcDXgH/ + A14B/wNeAf8DXgH/A14B/wNeAf8DVAGmAy4BSAMEAQYQAAMoATwDUwGlA2QB5wNeAf8DXgH/A14B/wNe + Af8DXgH/A14B/wNcAckDQwF3AwcBChAAAVYCVQGxA1UBtQNVAbUDVQG1A1cB6AFgAe0BkwH/AWUB7wGJ + Af8BQQHWAYEB/wNVAbUDVQG1A1UBtQNVAbUDGAEhDAADLQFGA1UBtQNVAbUDVQG1A1UBtQNVAbUDVQG1 + A1UBtQNVAbUDVQG1A1UBtQFWAlUBtBQAAwkBDANMAY8DXwHbA14B/wNeAf8DXgH/A18B8wNZAccDNAFU + FAADHwEsA0kBiANeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNcAc8DMAFMAxIBGBwA + A1UBsgFZAeUBiwH/AWAB6AGDAf8BQQHWAYEB/2QAAwEBAgMSARgDRwGCA14B/wNeAf8DXgH/A14B1QMo + ATwDCgEOFAADTgGZA2AB6wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNmAfcDYQHh + AzQBVBwAA1UBsgFQAdsBgQH/AVcB3gGAAf8BQAHVAWkB/2wAAyYBOANMAZADZAHnA1oBwAM9AWgDDAEQ + GAADNgFYA0cBgANHAYADRwGAA0cBgANHAYADRwGAA0cBgANHAYADRwGAA0cBgANHAYADRwGAAyEBMBwA + A1UBsgFHAdIBaAH/AUwB0wFfAf8BPwHUAWcB/3AAAxQBHANVAbUDQAFwdAADVAGrASIBuQEnAf8BIgG4 + AScB/wEgAbUBIwH/cAADBgEIAyMBNAMXASD/AP8AXgABQgFNAT4HAAE+AwABKAMAAUADAAEwAwABAQEA + AQEFAAGAAQEWAAP/AQAE/wQABP8EAAT/BAABnAEYAZwBGAQAAZgBGAGYARgEAAGYAYABmAGABAABgAGB + AYABgQQAAYEBwwGBAcMEAAGAAcMBgAHDBAABmAGBAZgBgQQABIAEAAGBAQgBgQEIBAABgwEYAYMBGAQA + BP8EAAT/BAAE/wQAAYMBgAHnAYcC/wHgAQcBgwGAAcMBhwL/AfABBwHDAYABgQGHAv8B/AE/AcMBgAEA + AYcC/wH4AT8BwwGAAQABhwL/AfABHwHDAYMBAAGDAcABBwHwAQ8BwwGDAcMBgwH4AR8B4AEHAcMBgwHD + AYMBgAEBAcABBwHDAYMBwwGDAYABAwGAAQMBAAGDAcMBgwHAAQMBgAEBAQABhwHDAYAB4AEHAYABAQEA + AYcBwwGAAeABDwL/AYEBhwHDAYAB8AEfAv8BwwGHAcMBgAH4AR8C/wHnAYcBwwGAAfwBPwb/AfwBfwr/ + AfwBPwb/AfwBPwb/AfwBPwT/AfwBfwH8AT8C/wGAAQEB+AEfAfwBPwL/AYABAQH4AR8BwAEBAcABAwGA + AQEB4AEPAcABAQHAAQMBwAEDAeABDwHAAQEBwAEDAcABAwHAAQMBwAEBAcABAwHgAQ8BgAEBAfwBPwL/ + AeABDwGAAQEB/AE/Av8B+AEfAYABAQH8AT8C/wH8AX8C/wH8AT8C/wH8AX8S/ws= diff --git a/Duplicati/GUI/Wizard pages/Add backup/EditFilters.cs b/Duplicati/GUI/Wizard pages/Add backup/EditFilters.cs index 2b88ec0bf..be22e0329 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/EditFilters.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/EditFilters.cs @@ -46,7 +46,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup if (args.Direction == System.Windows.Forms.Wizard.PageChangedDirection.Back) return; - m_wrapper.EncodedFilters = filterEditor1.Filter; + m_wrapper.EncodedFilterXml = filterEditor1.FilterXml; //Don't set args.NextPage, it runs on a list } @@ -55,7 +55,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup { m_wrapper = new WizardSettingsWrapper(m_settings); - filterEditor1.Filter = m_wrapper.EncodedFilters; + filterEditor1.FilterXml = m_wrapper.EncodedFilterXml; List> lst = new List>(); filterEditor1.BasePath = DynamicSetupHelper.GetSourceFolders(m_wrapper, new ApplicationSettings(m_wrapper.DataConnection ?? Program.DataConnection), lst); diff --git a/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs b/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs index bf6cf25d5..5253b1c29 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs @@ -205,7 +205,12 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup MessageBox.Show(this, Strings.SelectFiles.UpgradeWarning, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); string p = Library.Utility.Utility.AppendDirSeparator(m_wrapper.SourcePath); - List> filters = Library.Utility.FilenameFilter.DecodeFilter(m_wrapper.EncodedFilters); + System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); + doc.LoadXml(m_wrapper.EncodedFilterXml); + + List> filters = new List>(); + foreach (System.Xml.XmlNode n in doc.SelectNodes("root/filter")) + filters.Add(new KeyValuePair(bool.Parse(n.Attributes["include"].Value), n.Attributes["filter"].Value)); //See what folders are included with the current setup Library.Utility.FilenameFilter filter = new Duplicati.Library.Utility.FilenameFilter(filters); @@ -253,7 +258,19 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup //Make sure the extra filters are not included if (!unsupported) - m_wrapper.EncodedFilters = Library.Utility.FilenameFilter.EncodeAsFilter(filters); + { + doc = new System.Xml.XmlDocument(); + System.Xml.XmlNode root = doc.AppendChild(doc.CreateElement("root")); + foreach (KeyValuePair f in filters) + { + System.Xml.XmlNode n = root.AppendChild(doc.CreateElement("filter")); + n.Attributes.Append(doc.CreateAttribute("include")).Value = f.Key.ToString(); + n.Attributes.Append(doc.CreateAttribute("filter")).Value = f.Value; + n.Attributes.Append(doc.CreateAttribute("globbing")).Value = ""; + } + + m_wrapper.EncodedFilterXml = doc.OuterXml; + } if (unsupported) FolderRadio.Checked = true; diff --git a/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs b/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs index 0f126e6dc..98287ed45 100644 --- a/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs +++ b/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs @@ -120,7 +120,7 @@ namespace Duplicati.GUI.Wizard_pages this.ScheduleName = schedule.Name; this.SchedulePath = schedule.Path; this.SourcePath = schedule.Task.SourcePath; - this.EncodedFilters = schedule.Task.EncodedFilter; + this.EncodedFilterXml = schedule.Task.FilterXml; this.BackupPassword = schedule.Task.Encryptionkey; this.Backend = schedule.Task.Service; @@ -181,7 +181,7 @@ namespace Duplicati.GUI.Wizard_pages if (schedule.Task == null) schedule.Task = schedule.DataParent.Add(); schedule.Task.SourcePath = this.SourcePath; - schedule.Task.EncodedFilter = this.EncodedFilters; + schedule.Task.FilterXml = this.EncodedFilterXml; schedule.Task.Encryptionkey = this.BackupPassword; schedule.Task.Service = this.Backend; @@ -471,10 +471,10 @@ namespace Duplicati.GUI.Wizard_pages /// /// The filter applied to files being backed up /// - public string EncodedFilters + public string EncodedFilterXml { - get { return GetItem("EncodedFilters", ""); } - set { SetItem("EncodedFilters", value); } + get { return GetItem("EncodedFilterXml", ""); } + set { SetItem("EncodedFilterXml", value); } } ///