diff --git a/.vs/DataOrganizer/v16/.suo b/.vs/DataOrganizer/v16/.suo index 19a591d..8747cd4 100644 Binary files a/.vs/DataOrganizer/v16/.suo and b/.vs/DataOrganizer/v16/.suo differ diff --git a/DataOrganizer/FileManager.Designer.cs b/DataOrganizer/FileManager.Designer.cs index 9f2f4ba..639b5e7 100644 --- a/DataOrganizer/FileManager.Designer.cs +++ b/DataOrganizer/FileManager.Designer.cs @@ -49,12 +49,18 @@ this.CompareAgainstProfileComboBox = new System.Windows.Forms.ComboBox(); this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.SelectedGroupFolderViewGroupBox = new System.Windows.Forms.GroupBox(); + this.SelectedFolderViewGroupTreeView = new System.Windows.Forms.TreeView(); + this.ComparisionFolderViewGroupBox = new System.Windows.Forms.GroupBox(); + this.ComparisionFolderViewTreeView = new System.Windows.Forms.TreeView(); this.MainLayoutPanel.SuspendLayout(); this.MainMenuStrip.SuspendLayout(); this.DiffResultsGroupBox.SuspendLayout(); this.SelectedProfileInfoGroupBox.SuspendLayout(); this.CompareAgainstGroupBox.SuspendLayout(); this.statusStrip1.SuspendLayout(); + this.SelectedGroupFolderViewGroupBox.SuspendLayout(); + this.ComparisionFolderViewGroupBox.SuspendLayout(); this.SuspendLayout(); // // MainLayoutPanel @@ -70,6 +76,8 @@ this.MainLayoutPanel.Controls.Add(this.SelectedProfileInfoGroupBox, 0, 1); this.MainLayoutPanel.Controls.Add(this.CompareAgainstGroupBox, 1, 1); this.MainLayoutPanel.Controls.Add(this.statusStrip1, 0, 4); + this.MainLayoutPanel.Controls.Add(this.SelectedGroupFolderViewGroupBox, 2, 2); + this.MainLayoutPanel.Controls.Add(this.ComparisionFolderViewGroupBox, 2, 3); this.MainLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.MainLayoutPanel.Location = new System.Drawing.Point(0, 0); this.MainLayoutPanel.Name = "MainLayoutPanel"; @@ -280,6 +288,44 @@ this.StatusLabel.Size = new System.Drawing.Size(165, 25); this.StatusLabel.Text = "Nothing to report..."; // + // SelectedGroupFolderViewGroupBox + // + this.SelectedGroupFolderViewGroupBox.Controls.Add(this.SelectedFolderViewGroupTreeView); + this.SelectedGroupFolderViewGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.SelectedGroupFolderViewGroupBox.Location = new System.Drawing.Point(877, 221); + this.SelectedGroupFolderViewGroupBox.Name = "SelectedGroupFolderViewGroupBox"; + this.SelectedGroupFolderViewGroupBox.Size = new System.Drawing.Size(426, 351); + this.SelectedGroupFolderViewGroupBox.TabIndex = 10; + this.SelectedGroupFolderViewGroupBox.TabStop = false; + // + // SelectedFolderViewGroupTreeView + // + this.SelectedFolderViewGroupTreeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.SelectedFolderViewGroupTreeView.FullRowSelect = true; + this.SelectedFolderViewGroupTreeView.Location = new System.Drawing.Point(3, 22); + this.SelectedFolderViewGroupTreeView.Name = "SelectedFolderViewGroupTreeView"; + this.SelectedFolderViewGroupTreeView.Size = new System.Drawing.Size(420, 326); + this.SelectedFolderViewGroupTreeView.TabIndex = 0; + // + // ComparisionFolderViewGroupBox + // + this.ComparisionFolderViewGroupBox.Controls.Add(this.ComparisionFolderViewTreeView); + this.ComparisionFolderViewGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.ComparisionFolderViewGroupBox.Location = new System.Drawing.Point(877, 578); + this.ComparisionFolderViewGroupBox.Name = "ComparisionFolderViewGroupBox"; + this.ComparisionFolderViewGroupBox.Size = new System.Drawing.Size(426, 351); + this.ComparisionFolderViewGroupBox.TabIndex = 11; + this.ComparisionFolderViewGroupBox.TabStop = false; + // + // ComparisionFolderViewTreeView + // + this.ComparisionFolderViewTreeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.ComparisionFolderViewTreeView.FullRowSelect = true; + this.ComparisionFolderViewTreeView.Location = new System.Drawing.Point(3, 22); + this.ComparisionFolderViewTreeView.Name = "ComparisionFolderViewTreeView"; + this.ComparisionFolderViewTreeView.Size = new System.Drawing.Size(420, 326); + this.ComparisionFolderViewTreeView.TabIndex = 0; + // // FileManager // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); @@ -298,6 +344,8 @@ this.CompareAgainstGroupBox.ResumeLayout(false); this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); + this.SelectedGroupFolderViewGroupBox.ResumeLayout(false); + this.ComparisionFolderViewGroupBox.ResumeLayout(false); this.ResumeLayout(false); } @@ -325,5 +373,9 @@ private System.Windows.Forms.Button MoveNewFilesButton; private System.Windows.Forms.StatusStrip statusStrip1; private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.GroupBox SelectedGroupFolderViewGroupBox; + private System.Windows.Forms.TreeView SelectedFolderViewGroupTreeView; + private System.Windows.Forms.GroupBox ComparisionFolderViewGroupBox; + private System.Windows.Forms.TreeView ComparisionFolderViewTreeView; } } \ No newline at end of file diff --git a/DataOrganizer/FileManager.cs b/DataOrganizer/FileManager.cs index 52ce3be..89e1d76 100644 --- a/DataOrganizer/FileManager.cs +++ b/DataOrganizer/FileManager.cs @@ -4,7 +4,7 @@ using System.ComponentModel; using System.Data; using System.IO; using System.Linq; -using System.Text; +using System.Drawing; using System.Threading.Tasks; using System.Windows.Forms; @@ -15,6 +15,8 @@ namespace DataOrganizer private List Profiles { get; set; } = new List(); private List FolderGroups { get; set; } = new List(); private Snapshot ActiveSnapshot { get; set; } + private Snapshot ComparisionSnapshot { get; set; } + private Dictionary DiffTreeNodes { get; set; } = new Dictionary(); public FileManager() { @@ -26,10 +28,25 @@ namespace DataOrganizer CompareAgainstProfileComboBox.SelectedIndexChanged += CompareAgainstProfileComboBox_SelectedIndexChanged; CompareAgainstFolderGroupComboBox.SelectedIndexChanged += CompareAgainstFolderGroupComboBox_SelectedIndexChanged; CompareButton.Click += CompareButton_Click; + DiffViewTreeView.NodeMouseClick += DiffViewTreeView_NodeMouseClick; PopulateProfileComboBox(); } + private void DiffViewTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) + { + if (!ActiveSnapshot.TopLevelFolders.ContainsKey(e.Node.Name)) return; + + SelectedFolderViewGroupTreeView.Nodes.Clear(); + ComparisionFolderViewTreeView.Nodes.Clear(); + + var folderA = ActiveSnapshot.Directories[e.Node.Name]; + var folderB = ComparisionSnapshot.Directories[e.Node.Name]; + + SelectedFolderViewGroupTreeView.Nodes.Add(BuildTreeNode(folderA)); + ComparisionFolderViewTreeView.Nodes.Add(BuildTreeNode(folderB)); + } + private void ScanSelectedFolderGroupButton_Click(object sender, EventArgs e) { var folderGroup = GetSelectedFolderGroup(); @@ -43,12 +60,16 @@ namespace DataOrganizer MoveNewFilesButton.Enabled = true; if (ActiveSnapshot.Files.Count == 0) CommitFirstTimeScaneToDatabase(snapshot); + + //TODO: reload the form to have these changes active in the global snapshot } private void CommitFirstTimeScaneToDatabase(Snapshot snapshot) { var db = new DB(); db.InsertNewFileRecord(snapshot.Files.Values.ToList(), GetSelectedProfile().Id, GetSelectedFolderGroup().Id, GetSelectedFolderGroup().Path); + ClearForm(); + UpdateStatusLabel($"Committed {snapshot.Files.Count} records to the database."); } private void CompareButton_Click(object sender, EventArgs e) @@ -56,7 +77,57 @@ namespace DataOrganizer var db = new DB(); var p = GetProfileToCompare(); var f = GetFolderGroupToCompare(); + ComparisionSnapshot = new Snapshot(db.GetFilesForProfileByFolderGroup(p.Id, f.Id), f); + var diff = ActiveSnapshot.Diff(ComparisionSnapshot); + foreach(var file in diff.NewFiles) + AddFileSnapshotToDiffView(file, GetSelectedFolderGroup(), FileSnapshot.FileStatus.PendingInsert); + + foreach (var file in diff.ModifiedFiles) + AddFileSnapshotToDiffView(file, GetSelectedFolderGroup(), FileSnapshot.FileStatus.PendingUpdate); + + foreach (var file in diff.DeletedFiles) + AddFileSnapshotToDiffView(file, GetSelectedFolderGroup(), FileSnapshot.FileStatus.PendingDelete); + } + + private void AddFileSnapshotToDiffView(FileSnapshot file, DB.FolderGroup folderGroup, FileSnapshot.FileStatus fileStatus = FileSnapshot.FileStatus.None) + { + var folder = file.ParentFolder; + + while (folder != null) + { + if (folder.FullPath == folderGroup.Path) break; + + var n = new TreeNode(folder.Name) { Name = folder.FullPath }; + if (!DiffTreeNodes.ContainsKey(n.Name)) + { + if(folder.Parent != null && folder.Parent.FullPath == folderGroup.Path) + { + DiffViewTreeView.Nodes.Add(n); + } + DiffTreeNodes.Add(n.Name, n); + } + + folder = folder.Parent; + } + + var node = new TreeNode(file.Name) { Name = file.FullPath }; + DiffTreeNodes.Add(file.FullPath, node); + DiffTreeNodes[file.ParentFolder.FullPath].Nodes.Add(node); + + switch (fileStatus) + { + case FileSnapshot.FileStatus.PendingInsert: + node.BackColor = Color.LightBlue; + break; + case FileSnapshot.FileStatus.PendingUpdate: + node.BackColor = Color.Orange; + node.ForeColor = Color.White; + break; + case FileSnapshot.FileStatus.PendingDelete: + node.BackColor = Color.Red; + break; + } } private void CompareAgainstProfileComboBox_SelectedIndexChanged(object sender, EventArgs e) @@ -78,6 +149,8 @@ namespace DataOrganizer ClearDiffResults(); CompareButton.Enabled = ActiveSnapshot.Files.Count > 0; + + ComparisionFolderViewGroupBox.Text = $"Folder View of {GetProfileToCompare().Name}:"; } private void SelectFolderGroupComboBoxMainMenu_SelectedIndexChanged(object sender, EventArgs e) @@ -104,6 +177,7 @@ namespace DataOrganizer ScanSelectedFolderGroupButton.Text = "Scan Folder Group"; SelectedProfileDataLabel.Text = $"Loaded snapshot data for {files.Count} file(s)."; + SelectedGroupFolderViewGroupBox.Text = $"Folder View of {GetSelectedProfile().Name}:"; } private TreeNode BuildTreeNode(Folder folder) @@ -175,6 +249,10 @@ namespace DataOrganizer ScanSelectedFolderGroupButton.Text = "Scan for Changes"; MoveNewFilesButton.Enabled = false; CommitFilesChangesButton.Enabled = false; + SelectedGroupFolderViewGroupBox.Text = string.Empty; + SelectedFolderViewGroupTreeView.Nodes.Clear(); + ComparisionFolderViewGroupBox.Text = string.Empty; + ComparisionFolderViewTreeView.Nodes.Clear(); } private void ClearDiffResults() diff --git a/DataOrganizer/FileManager.resx b/DataOrganizer/FileManager.resx index 0e5bf2c..57b87f9 100644 --- a/DataOrganizer/FileManager.resx +++ b/DataOrganizer/FileManager.resx @@ -123,4 +123,10 @@ 205, 17 + + 17, 17 + + + 205, 17 + \ No newline at end of file diff --git a/DataOrganizer/Snapshot.cs b/DataOrganizer/Snapshot.cs index 8c8af3d..e009b0a 100644 --- a/DataOrganizer/Snapshot.cs +++ b/DataOrganizer/Snapshot.cs @@ -17,7 +17,7 @@ namespace DataOrganizer //Contains files associated with particular, first level folders. //So if the root folder group is X:\Anime and we have a folder path of x:\Anime\Death Note, then indexing this dictonary //with the text "Death Note" would return all files in that folder. - public Dictionary> OrganizationFolders { get; private set; } = new Dictionary>(); + public Dictionary> TopLevelFolders { get; private set; } = new Dictionary>(); public Snapshot(List fileRecords, DB.FolderGroup folderGroup) { @@ -53,7 +53,7 @@ namespace DataOrganizer { firstLevelFolder = new Folder(folders[0], Path.Combine(folderGroup.Path, folders[0]), Root); Directories.Add(orgFolder, firstLevelFolder); - OrganizationFolders.Add(orgFolder, new List()); + TopLevelFolders.Add(orgFolder, new List()); Root.AddDirectory(firstLevelFolder); } @@ -81,7 +81,7 @@ namespace DataOrganizer //} var snap = new FileSnapshot(file, firstLevelFolder, Directories[currentPath], folderGroup.Path); - OrganizationFolders[orgFolder].Add(snap); + TopLevelFolders[orgFolder].Add(snap); Directories[currentPath].AddFile(snap); Files.Add(Path.Combine(folderGroup.Path, file.PathNoRoot), snap); } @@ -103,7 +103,7 @@ namespace DataOrganizer { firstLevelFolder = new Folder(folders[0], Path.Combine(folderGroup.Path, folders[0]), Root); Directories.Add(orgFolder, firstLevelFolder); - OrganizationFolders.Add(orgFolder, new List()); + TopLevelFolders.Add(orgFolder, new List()); Root.AddDirectory(firstLevelFolder); } @@ -131,7 +131,7 @@ namespace DataOrganizer //} var snap = new FileSnapshot(file, firstLevelFolder, Directories[currentPath], folderGroup.Path); - OrganizationFolders[orgFolder].Add(snap); + TopLevelFolders[orgFolder].Add(snap); Directories[currentPath].AddFile(snap); Files.Add(snap.FullPath, snap); } @@ -157,7 +157,7 @@ namespace DataOrganizer private void ClearSubFolders(Folder folder) { if (Directories.ContainsKey(folder.FullPath)) Directories.Remove(folder.FullPath); - if (OrganizationFolders.ContainsKey(folder.FullPath)) OrganizationFolders.Remove(folder.FullPath); + if (TopLevelFolders.ContainsKey(folder.FullPath)) TopLevelFolders.Remove(folder.FullPath); Root.DeleteFolder(folder); folder.Parent.DeleteFolder(folder); @@ -173,12 +173,12 @@ namespace DataOrganizer foreach(var file in snapshot.Files) if (!Files.ContainsKey(file.Key)) newFiles.Add(file.Value); - foreach (var folder in snapshot.OrganizationFolders) + foreach (var folder in snapshot.TopLevelFolders) { - if (!OrganizationFolders.ContainsKey(folder.Key) && folder.Key != Root.FullPath) + if (!TopLevelFolders.ContainsKey(folder.Key) && folder.Key != Root.FullPath) { Root.AddDirectory(snapshot.Directories[folder.Key]); - OrganizationFolders.Add(folder.Key, new List()); + TopLevelFolders.Add(folder.Key, new List()); } } @@ -207,7 +207,7 @@ namespace DataOrganizer folder = folder.Parent; } - OrganizationFolders[newFile.OrganizationalFolder.FullPath].Add(newFile); + TopLevelFolders[newFile.TopLevelFolder.FullPath].Add(newFile); } } @@ -227,9 +227,9 @@ namespace DataOrganizer foreach (var file in b.Files) if (!a.Files.ContainsKey(file.Key)) newFiles.Add(file.Value); - foreach (var folder in b.OrganizationFolders) + foreach (var folder in b.TopLevelFolders) { - if (!a.OrganizationFolders.ContainsKey(folder.Key) && folder.Key != a.Root.FullPath) + if (!a.TopLevelFolders.ContainsKey(folder.Key) && folder.Key != a.Root.FullPath) { newOrgFolders.Add(b.Directories[folder.Key]); } @@ -252,10 +252,26 @@ namespace DataOrganizer NewFiles = newFiles, ModifiedFiles = modifiedFiles, DeletedFiles = deletedFiles, - NewOrganizationalFolders = newOrgFolders + NewTopLevelFolders = newOrgFolders }; } + public List FindFileRenames(Folder a, Folder b) + { + var renames = new List(); + + foreach(var file in a.Files.Values) + { + foreach(var f in b.Files.Values) + { + if (file.Size == f.Size && file.CreatedDate == f.CreatedDate && file.ModifiedDate == f.ModifiedDate) + renames.Add(new SnapshotComparsion.RenamedFile() { From = file, To = f }); + } + } + + return renames; + } + public struct Duplicate { public DB.DBFileSnapshot File; @@ -319,11 +335,23 @@ namespace DataOrganizer { if (Folders.ContainsKey(folder.FullPath)) Folders.Remove(folder.FullPath); } + + public List GetAllFiles() + { + var files = new List(); + + files.AddRange(Files.Values); + + foreach (var dir in Folders.Values) + files.AddRange(dir.GetAllFiles()); + + return files; + } } public class FileSnapshot { - public Folder OrganizationalFolder { get; } + public Folder TopLevelFolder { get; } public Folder ParentFolder { get; } public string PathNoRoot { get; } private string Root { get; } @@ -373,7 +401,7 @@ namespace DataOrganizer public FileSnapshot(DB.DBFileSnapshot file, Folder organizationalFolder, Folder parentFolder, string rootPath) { - OrganizationalFolder = organizationalFolder; + TopLevelFolder = organizationalFolder; ParentFolder = parentFolder; var db = new DB(); @@ -392,7 +420,7 @@ namespace DataOrganizer public FileSnapshot(FileInfo file, Folder organizationalFolder, Folder parentFolder, string rootPath) { - OrganizationalFolder = organizationalFolder; + TopLevelFolder = organizationalFolder; ParentFolder = parentFolder; _Name = file.Name; @@ -442,6 +470,13 @@ namespace DataOrganizer public List NewFiles { get; set; } public List ModifiedFiles { get; set; } public List DeletedFiles { get; set; } - public List NewOrganizationalFolders { get; set; } + public List NewTopLevelFolders { get; set; } + public List RenamedFiles { get; set; } + + public struct RenamedFile + { + public FileSnapshot From; + public FileSnapshot To; + } } }