Files
duplicati/Duplicati/GUI/ListBackupFiles.cs
T
kenneth@hexad.dk a60bd9511f Large refactoring, removing duplicate code in the former Duplicati gui, because it is now hosted in the server.
Not 100% tested, because it is supposed to go away soon, but right now it is the only way to create a new backup.
Also moved database schema and upgrade information/code into the data model project.

git-svn-id: https://duplicati.googlecode.com/svn/trunk@1275 59da171f-624f-0410-aa54-27559c288bec
2012-05-14 18:53:07 +00:00

294 lines
13 KiB
C#

#region Disclaimer / License
// Copyright (C) 2011, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Duplicati.Server;
namespace Duplicati.GUI
{
public partial class ListBackupFiles : Form
{
private object m_lock = new object();
private System.Threading.Thread m_thread = null;
private const string FOLDER_IMAGE_KEY = "folder";
private const string NEW_FOLDER_IMAGE_KEY = "new folder";
private const string REMOVED_FOLDER_IMAGE_KEY = "removed folder";
private const string ADDED_OR_MODIFIED_FILE_IMAGE_KEY = "added or modified file";
private const string CONTROL_FILE_IMAGE_KEY = "control file";
private const string DELETED_FILE_IMAGE_KEY = "deleted file";
private const string ADDED_FILE_IMAGE_KEY = "added file";
private const string MODIFIED_FILE_IMAGE_KEY = "modified file";
private const string INCOMPLETE_FILE_IMAGE_KEY = "incomplete file";
public ListBackupFiles()
{
InitializeComponent();
imageList.Images.Add(FOLDER_IMAGE_KEY, Properties.Resources.FolderOpen);
imageList.Images.Add(NEW_FOLDER_IMAGE_KEY, Properties.Resources.AddedFolder);
imageList.Images.Add(REMOVED_FOLDER_IMAGE_KEY, Properties.Resources.DeletedFolder);
imageList.Images.Add(ADDED_OR_MODIFIED_FILE_IMAGE_KEY, Properties.Resources.AddedOrModifiedFile);
imageList.Images.Add(CONTROL_FILE_IMAGE_KEY, Properties.Resources.ControlFile);
imageList.Images.Add(DELETED_FILE_IMAGE_KEY, Properties.Resources.DeletedFile);
imageList.Images.Add(ADDED_FILE_IMAGE_KEY, Properties.Resources.AddedFile);
imageList.Images.Add(MODIFIED_FILE_IMAGE_KEY, Properties.Resources.ModifiedFile);
imageList.Images.Add(INCOMPLETE_FILE_IMAGE_KEY, Properties.Resources.IncompleteFile);
this.Icon = Properties.Resources.TrayNormal;
#if DEBUG
this.Text += " (DEBUG)";
#endif
}
public void ShowList(Control owner, Datamodel.Schedule schedule, DateTime when)
{
backgroundWorker1.RunWorkerAsync(new object[] { schedule, when });
this.ShowDialog(owner);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
lock (m_lock)
m_thread = System.Threading.Thread.CurrentThread;
try
{
object[] args = (object[])e.Argument;
DuplicatiRunner r = new DuplicatiRunner();
IList<string> sourceFolders = r.ListSourceFolders((Datamodel.Schedule)args[0], (DateTime)args[1]);
if (r.IsAborted)
e.Cancel = true;
else
{
r = new DuplicatiRunner();
List<KeyValuePair<Library.Main.RSync.RSyncDir.PatchFileType, string>> files = r.ListActualFiles((Datamodel.Schedule)args[0], (DateTime)args[1]);
e.Result = new KeyValuePair<IList<string>, List<KeyValuePair<Library.Main.RSync.RSyncDir.PatchFileType, string>>>(sourceFolders, files);
if (r.IsAborted)
e.Cancel = true;
}
}
catch (System.Threading.ThreadAbortException)
{
System.Threading.Thread.ResetAbort();
e.Cancel = true;
}
finally
{
lock (m_lock)
m_thread = null;
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//If the user has closed, ignore any results
if (!this.Visible)
return;
if (e.Cancelled)
this.Close();
else if (e.Error != null || e.Result == null)
{
Exception ex = e.Error;
if (ex == null)
ex = new Exception(Strings.ListBackupFiles.NoDataError);
MessageBox.Show(this, string.Format(Strings.Common.GenericError, ex.ToString()), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
this.Close();
}
else
{
try
{
ContentTree.BeginUpdate();
KeyValuePair<IList<string>, List<KeyValuePair<Library.Main.RSync.RSyncDir.PatchFileType, string>>> res = (KeyValuePair<IList<string>, List<KeyValuePair<Library.Main.RSync.RSyncDir.PatchFileType, string>>>)e.Result;
IList<string> sourcefolders = res.Key;
List<KeyValuePair<Library.Main.RSync.RSyncDir.PatchFileType, string>> entries = res.Value;
List<string> addedfolders = new List<string>();
List<string> removedfolders = new List<string>();
List<string> addedOrUpdatedfiles = new List<string>();
List<string> updatedfiles = new List<string>();
List<string> addedfiles = new List<string>();
List<string> incompletefiles = new List<string>();
List<string> deletedfiles = new List<string>();
List<string> controlfiles = new List<string>();
foreach (KeyValuePair<Library.Main.RSync.RSyncDir.PatchFileType, string> x in entries)
switch (x.Key)
{
case Duplicati.Library.Main.RSync.RSyncDir.PatchFileType.AddedFolder:
addedfolders.Add(x.Value);
break;
case Duplicati.Library.Main.RSync.RSyncDir.PatchFileType.DeletedFolder:
removedfolders.Add(x.Value);
break;
case Duplicati.Library.Main.RSync.RSyncDir.PatchFileType.AddedOrUpdatedFile:
addedOrUpdatedfiles.Add(x.Value);
break;
case Duplicati.Library.Main.RSync.RSyncDir.PatchFileType.AddedFile:
addedfiles.Add(x.Value);
break;
case Duplicati.Library.Main.RSync.RSyncDir.PatchFileType.UpdatedFile:
updatedfiles.Add(x.Value);
break;
case Duplicati.Library.Main.RSync.RSyncDir.PatchFileType.IncompleteFile:
incompletefiles.Add(x.Value);
break;
case Duplicati.Library.Main.RSync.RSyncDir.PatchFileType.ControlFile:
controlfiles.Add(x.Value);
break;
case Duplicati.Library.Main.RSync.RSyncDir.PatchFileType.DeletedFile:
deletedfiles.Add(x.Value);
break;
}
addedfolders.Sort();
removedfolders.Sort();
deletedfiles.Sort();
addedOrUpdatedfiles.Sort();
addedfiles.Sort();
updatedfiles.Sort();
incompletefiles.Sort();
controlfiles.Sort();
foreach (string s in addedfolders)
AddTreeItem(s, NEW_FOLDER_IMAGE_KEY);
foreach (string s in removedfolders)
AddTreeItem(s, REMOVED_FOLDER_IMAGE_KEY);
foreach (string s in addedOrUpdatedfiles)
AddTreeItem(s, ADDED_OR_MODIFIED_FILE_IMAGE_KEY);
foreach (string s in addedfiles)
AddTreeItem(s, ADDED_FILE_IMAGE_KEY);
foreach (string s in updatedfiles)
AddTreeItem(s, MODIFIED_FILE_IMAGE_KEY);
foreach (string s in incompletefiles)
AddTreeItem(s, INCOMPLETE_FILE_IMAGE_KEY);
foreach (string s in controlfiles)
AddTreeItem(s, CONTROL_FILE_IMAGE_KEY);
foreach (string s in deletedfiles)
AddTreeItem(s, DELETED_FILE_IMAGE_KEY);
//Patch display to show actual source folder rather than the internal enumeration system
if (sourcefolders != null && sourcefolders.Count > 1)
{
foreach (TreeNode t in ContentTree.Nodes)
{
int ix;
if (int.TryParse(t.Text, out ix))
{
if (ix >= 0 && ix < sourcefolders.Count)
t.Text = sourcefolders[ix];
}
}
}
}
finally
{
ContentTree.EndUpdate();
ContentPanel.Visible = true;
}
}
}
private void AddTreeItem(string value, string imagekey)
{
if (value.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()))
value = value.Substring(0, value.Length - 1);
string[] items = value.Split(System.IO.Path.DirectorySeparatorChar);
TreeNodeCollection parent = ContentTree.Nodes;
for (int i = 0; i < items.Length; i++)
{
TreeNode match = null;
foreach (TreeNode n in parent)
if (n.Text == items[i])
{
match = n;
break;
}
if (match == null)
{
match = new TreeNode(items[i]);
match.ImageKey = match.SelectedImageKey =
i == items.Length - 1 ? imagekey : FOLDER_IMAGE_KEY;
switch (match.ImageKey)
{
case FOLDER_IMAGE_KEY:
match.ToolTipText = Strings.ListBackupFiles.TooltipExistingFolder;
break;
case NEW_FOLDER_IMAGE_KEY:
match.ToolTipText = Strings.ListBackupFiles.TooltipAddedFolder;
break;
case REMOVED_FOLDER_IMAGE_KEY:
match.ToolTipText = Strings.ListBackupFiles.TooltipDeletedFolder;
break;
case ADDED_OR_MODIFIED_FILE_IMAGE_KEY:
match.ToolTipText = Strings.ListBackupFiles.TooltipAddedOrModifiedFile;
break;
case ADDED_FILE_IMAGE_KEY:
match.ToolTipText = Strings.ListBackupFiles.TooltipAddedFile;
break;
case MODIFIED_FILE_IMAGE_KEY:
match.ToolTipText = Strings.ListBackupFiles.TooltipModifiedFile;
break;
case INCOMPLETE_FILE_IMAGE_KEY:
match.ToolTipText = Strings.ListBackupFiles.TooltipIncompleteFile;
break;
case CONTROL_FILE_IMAGE_KEY:
match.ToolTipText = Strings.ListBackupFiles.TooltipControlFile;
break;
case DELETED_FILE_IMAGE_KEY:
match.ToolTipText = Strings.ListBackupFiles.TooltipDeletedFile;
break;
}
parent.Add(match);
}
parent = match.Nodes;
}
}
private void ListBackupFiles_FormClosing(object sender, FormClosingEventArgs e)
{
lock (m_lock)
if (m_thread != null)
m_thread.Abort();
}
}
}