Files
duplicati/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs
T
kenneth.skovhede@gmail.com 3dc9ced4e8 Filters are now supported.
Most of the wizard functionality is restored.

git-svn-id: https://duplicati.googlecode.com/svn/trunk@75 59da171f-624f-0410-aa54-27559c288bec
2009-02-01 23:20:07 +00:00

434 lines
18 KiB
C#

#region Disclaimer / License
// Copyright (C) 2008, 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.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Wizard;
using Duplicati.Datamodel;
namespace Duplicati.GUI.Wizard_pages.Add_backup
{
public partial class SelectFiles : WizardControl
{
private WorkerThread<string> m_calculator;
private object m_lock = new object();
private Dictionary<string, long> m_sizes;
private Schedule m_schedule;
private string m_myPictures;
private string m_myMusic;
private string m_desktop;
private string m_appData;
private string m_myDocuments;
private string[] m_specialFolders;
public SelectFiles()
: base("Select files to backup", "On this page you must select the folder and files you wish to backup")
{
InitializeComponent();
m_sizes = new Dictionary<string, long>();
m_myPictures = Library.Core.Utility.AppendDirSeperator("!" + System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures));
m_myMusic = Library.Core.Utility.AppendDirSeperator("!" + System.Environment.GetFolderPath(Environment.SpecialFolder.MyMusic));
m_desktop = Library.Core.Utility.AppendDirSeperator("!" + System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
m_appData = Library.Core.Utility.AppendDirSeperator("!" + System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
m_myDocuments = Library.Core.Utility.AppendDirSeperator("!" + System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
FolderTooltip.SetToolTip(IncludeDocuments, m_myDocuments.Substring(1));
FolderTooltip.SetToolTip(IncludeMusic, m_myMusic.Substring(1));
FolderTooltip.SetToolTip(IncludeImages, m_myPictures.Substring(1));
FolderTooltip.SetToolTip(IncludeDesktop, m_desktop.Substring(1));
FolderTooltip.SetToolTip(IncludeSettings, m_appData.Substring(1));
m_specialFolders = new string[] {
m_myDocuments.Substring(1),
m_myMusic.Substring(1),
m_myPictures.Substring(1),
m_appData.Substring(1),
m_desktop.Substring(1)
};
base.PageEnter += new PageChangeHandler(SelectFiles_PageEnter);
base.PageLeave += new PageChangeHandler(SelectFiles_PageLeave);
}
void SelectFiles_PageLeave(object sender, PageChangedArgs args)
{
m_settings["Files:Sizes"] = m_sizes;
if (args.Direction == PageChangedDirection.Back)
return;
if (DocumentsRadio.Checked)
{
List<string> folders = new List<string>();
List<string> exfolders = new List<string>();
if (IncludeDocuments.Checked)
folders.Add(m_myDocuments.Substring(1));
else
exfolders.Add(m_myDocuments.Substring(1));
if (IncludeImages.Checked)
folders.Add(m_myPictures.Substring(1));
else
exfolders.Add(m_myPictures.Substring(1));
if (IncludeMusic.Checked)
folders.Add(m_myMusic.Substring(1));
else
exfolders.Add(m_myMusic.Substring(1));
if (IncludeDesktop.Checked)
folders.Add(m_desktop.Substring(1));
else
exfolders.Add(m_desktop.Substring(1));
if (IncludeSettings.Checked)
folders.Add(m_appData.Substring(1));
else
exfolders.Add(m_appData.Substring(1));
if (folders.Count == 0)
{
MessageBox.Show(this, "You have not included any files.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
args.Cancel = true;
return;
}
//Find the most common root
string basefolder = folders[0];
bool hasCommonParent = false;
foreach (string f in folders)
if (basefolder.StartsWith(f))
basefolder = f;
else if (!f.StartsWith(basefolder))
{
string[] p1 = basefolder.Split(System.IO.Path.DirectorySeparatorChar);
string[] p2 = f.Split(System.IO.Path.DirectorySeparatorChar);
int ix = 0;
while (p1.Length > ix && p2.Length > ix && p1[ix] == p2[ix])
ix++;
if (ix == 0)
{
MessageBox.Show(this, "Due to your machine setup, it is not possible to backup\nthe selected folders in the same backup.\nTry unchecking some items, and create more than one backup.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
args.Cancel = true;
return;
}
hasCommonParent = true;
basefolder = Library.Core.Utility.AppendDirSeperator(string.Join(System.IO.Path.DirectorySeparatorChar.ToString(), p1, 0, ix));
}
m_schedule.Tasks[0].SourcePath = basefolder;
List<TaskFilter> filters = new List<TaskFilter>();
//Exclude everything if they have a non-included parent
if (hasCommonParent)
{
TaskFilter tf = m_schedule.DataParent.Add<TaskFilter>();
tf.Include = false;
tf.Filter = Library.Core.FilenameFilter.ConvertGlobbingToRegExp(basefolder + "*");
filters.Add(tf);
}
//Include selected folders
foreach (string f in folders)
{
TaskFilter tfx = m_schedule.DataParent.Add<TaskFilter>();
tfx.Include = true;
tfx.Filter = Library.Core.FilenameFilter.ConvertGlobbingToRegExp(f + "*");
filters.Add(tfx);
//Exclude subfolders
foreach (string s in exfolders)
if (s.StartsWith(f) && (basefolder == s || s.StartsWith(basefolder)))
{
TaskFilter tfp = m_schedule.DataParent.Add<TaskFilter>();
tfp.Include = false;
tfp.Filter = Library.Core.FilenameFilter.ConvertGlobbingToRegExp(s + "*");
filters.Add(tfp);
}
}
List<TaskFilter> extras = new List<TaskFilter>();
string key = Library.Core.FilenameFilter.ConvertGlobbingToRegExp(basefolder);
foreach(TaskFilter tf in m_schedule.Tasks[0].Filters)
if (!tf.Filter.StartsWith(key))
extras.Add(tf);
if (filters.Count < 2)
m_schedule.Tasks[0].SortedFilters = extras.ToArray();
else
{
filters.AddRange(extras);
m_schedule.Tasks[0].SortedFilters = filters.ToArray();
}
}
else
{
if (!System.IO.Directory.Exists(TargetFolder.Text))
{
MessageBox.Show(this, "The folder \"" + TargetFolder.Text + "\" does not exist.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
args.Cancel = true;
return;
}
m_schedule.Tasks[0].SourcePath = TargetFolder.Text;
}
if (m_calculator != null)
m_calculator.ClearQueue(true);
args.NextPage = new SelectBackend();
}
void SelectFiles_PageEnter(object sender, PageChangedArgs args)
{
m_schedule = (Schedule)m_settings["Schedule"];
if (m_settings.ContainsKey("Files:Sizes"))
m_sizes = (Dictionary<string, long>)m_settings["Files:Sizes"];
if (!m_valuesAutoLoaded)
{
List<string> filters = new List<string>();
foreach (TaskFilter tf in m_schedule.Tasks[0].Filters)
if (tf.Include && tf.Filter.StartsWith(Library.Core.FilenameFilter.ConvertGlobbingToRegExp(m_schedule.Tasks[0].SourcePath)))
filters.Add(tf.Filter);
if (filters.Count == 0)
TargetFolder.Text = m_schedule.Path;
List<string> included = new List<string>();
foreach (string s in m_specialFolders)
if (filters.Contains(Library.Core.FilenameFilter.ConvertGlobbingToRegExp(s + "*")))
included.Add(s);
if (included.Count == 0)
{
FolderRadio.Checked = true;
TargetFolder.Text = m_schedule.Path;
}
else
{
DocumentsRadio.Checked = true;
IncludeDocuments.Checked = included.Contains(m_myDocuments.Substring(1));
IncludeImages.Checked = included.Contains(m_myPictures.Substring(1));
IncludeMusic.Checked = included.Contains(m_myMusic.Substring(1));
IncludeDesktop.Checked = included.Contains(m_desktop.Substring(1));
IncludeSettings.Checked = included.Contains(m_appData.Substring(1));
if (!(IncludeDocuments.Checked || IncludeMusic.Checked || IncludeImages.Checked || IncludeDesktop.Checked || IncludeSettings.Checked))
{
FolderRadio.Checked = true;
TargetFolder.Text = m_schedule.Path;
}
}
}
if (FolderRadio.Checked)
TargetFolder_Leave(null, null);
else
Rescan();
}
private void StartCalculator()
{
if (m_calculator == null)
{
totalSize.Text = "Calculating size ...";
m_calculator = new WorkerThread<string>(CalculateFolderSize);
m_calculator.CompletedWork += new EventHandler(m_calculator_CompletedWork);
}
}
void m_calculator_CompletedWork(object sender, EventArgs e)
{
if (this.InvokeRequired)
this.Invoke(new EventHandler(m_calculator_CompletedWork), sender, e);
else
{
if (m_calculator == null)
return;
long s = 0;
if (DocumentsRadio.Checked)
{
if (m_sizes.ContainsKey(m_myDocuments) && IncludeDocuments.Checked)
s += m_sizes[m_myDocuments];
if (m_sizes.ContainsKey(m_myMusic) && IncludeMusic.Checked)
s += m_sizes[m_myMusic];
if (m_sizes.ContainsKey(m_myPictures) && IncludeImages.Checked)
s += m_sizes[m_myPictures];
if (m_sizes.ContainsKey(m_appData) && IncludeSettings.Checked)
s += m_sizes[m_appData];
if (m_sizes.ContainsKey(m_desktop) && IncludeDesktop.Checked)
s += m_sizes[m_desktop];
}
else
s = m_sizes.ContainsKey(TargetFolder.Text) ? m_sizes[TargetFolder.Text] : 0;
if (m_calculator.CurrentTasks.Count == 0 && !m_calculator.Active)
totalSize.Text = string.Format("The selected items take up {0} of space", Library.Core.Utility.FormatSizeString(s));
else
totalSize.Text = string.Format("Calculating ... (using more than {0} of space)", Library.Core.Utility.FormatSizeString(s));
if (m_sizes.ContainsKey(m_myMusic))
myMusicSize.Text = Library.Core.Utility.FormatSizeString(m_sizes[m_myMusic]);
if (m_sizes.ContainsKey(m_myPictures))
myPicturesSize.Text = Library.Core.Utility.FormatSizeString(m_sizes[m_myPictures]);
if (m_sizes.ContainsKey(m_desktop))
desktopSize.Text = Library.Core.Utility.FormatSizeString(m_sizes[m_desktop]);
if (m_sizes.ContainsKey(m_appData))
appdataSize.Text = Library.Core.Utility.FormatSizeString(m_sizes[m_appData]);
if (m_sizes.ContainsKey(m_myDocuments))
myDocumentsSize.Text = Library.Core.Utility.FormatSizeString(m_sizes[m_myDocuments]);
if (m_sizes.ContainsKey(TargetFolder.Text))
customSize.Text = Library.Core.Utility.FormatSizeString(m_sizes[TargetFolder.Text]);
}
}
private void Rescan()
{
lock (m_lock)
{
StartCalculator();
if (!m_sizes.ContainsKey(m_myMusic))
m_calculator.AddTask(m_myMusic);
if (!m_sizes.ContainsKey(m_myPictures))
m_calculator.AddTask(m_myPictures);
if (!m_sizes.ContainsKey(m_desktop))
m_calculator.AddTask(m_desktop);
if (!m_sizes.ContainsKey(m_appData))
m_calculator.AddTask(m_appData);
if (!m_sizes.ContainsKey(m_myDocuments))
m_calculator.AddTask(m_myDocuments);
m_calculator_CompletedWork(null, null);
}
}
private void BrowseFolderButton_Click(object sender, EventArgs e)
{
if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK)
{
TargetFolder.Text = folderBrowserDialog.SelectedPath;
TargetFolder_Leave(null, null);
}
}
private void TargetType_CheckedChanged(object sender, EventArgs e)
{
DocumentGroup.Enabled = DocumentsRadio.Checked;
FolderGroup.Enabled = FolderRadio.Checked;
if (DocumentsRadio.Checked)
Rescan();
else
TargetFolder_Leave(sender, e);
}
private void CalculateFolderSize(string folder)
{
lock (m_lock)
if (m_sizes.ContainsKey(folder))
return;
long size = 0;
Library.Core.FilenameFilter fnf = null;
string folderkey = folder;
//Special folders, extended logic
if (folder.StartsWith("!"))
{
folder = folder.Substring(1);
List<KeyValuePair<bool, string>> filters = new List<KeyValuePair<bool,string>>();
filters.Add(new KeyValuePair<bool, string>(true, Library.Core.FilenameFilter.ConvertGlobbingToRegExp(folder + "*")));
foreach (string s in m_specialFolders)
if (s != folder && s.StartsWith(folder))
filters.Add(new KeyValuePair<bool, string>(false, Library.Core.FilenameFilter.ConvertGlobbingToRegExp(s + "*")));
if (filters.Count > 1)
fnf = new Duplicati.Library.Core.FilenameFilter(filters);
}
if (System.IO.Directory.Exists(folder))
{
try
{
foreach (string file in Duplicati.Library.Core.Utility.EnumerateFiles(folder, fnf))
try { size += new System.IO.FileInfo(file).Length; }
catch { }
}
catch { }
}
lock (m_lock)
m_sizes[folderkey] = size;
}
private void TargetFolder_Leave(object sender, EventArgs e)
{
lock (m_lock)
if (TargetFolder.Text.Trim().Length > 0 && !m_sizes.ContainsKey(TargetFolder.Text))
{
StartCalculator();
m_calculator.ClearQueue(true);
m_calculator.AddTask(TargetFolder.Text);
m_calculator_CompletedWork(null, null);
}
else if (TargetFolder.Text == "")
totalSize.Text = "";
else if (m_sizes.ContainsKey(TargetFolder.Text))
{
StartCalculator();
m_calculator.ClearQueue(true);
m_calculator_CompletedWork(null, null);
}
}
private void SelectFiles_VisibleChanged(object sender, EventArgs e)
{
if (!this.Visible && m_calculator != null)
{
m_calculator.Terminate(false);
m_calculator = null;
}
}
}
}