diff --git a/.vs/DataOrganizer/v16/.suo b/.vs/DataOrganizer/v16/.suo index 6f40d3a..6a8e369 100644 Binary files a/.vs/DataOrganizer/v16/.suo and b/.vs/DataOrganizer/v16/.suo differ diff --git a/DataOrganizer/DB.cs b/DataOrganizer/DB.cs index c3b0dc8..29ecb0c 100644 --- a/DataOrganizer/DB.cs +++ b/DataOrganizer/DB.cs @@ -347,6 +347,80 @@ namespace DataOrganizer return true; } + public List GetFilesForProfileByFolderGroup(int profileId, int folderGroupId) + { + var files = new List(); + + var query = @"SELECT * FROM main.file INNER JOIN main.folder_root ON main.file.folder_root_id = main.folder_root.root_id WHERE main.file.profile_id = @ProfileId AND folder_root_id = @GroupId ORDER BY main.file.full_path ASC"; + + using (var connection = new SqliteConnection(ConnectionString)) + { + using (var command = new SqliteCommand(query, connection)) + { + command.Parameters.AddWithValue("ProfileId", profileId); + command.Parameters.AddWithValue("GroupId", folderGroupId); + connection.Open(); + + var reader = command.ExecuteReader(); + + while(reader.Read()) + { + var fullPath = string.Format("{0}{1}", reader["path"], reader["full_path"]); + + files.Add(new FileSnapshot + { + Id = Convert.ToInt32(reader["file_id"]), + FullPath = fullPath, + Name = reader["name"].ToString(), + ProfileId = profileId, + RootFolderId = folderGroupId, + Size = Convert.ToInt64(reader["size"]), + CreationDate = Convert.ToDateTime(reader["date_created"]), + ModifiedDate = Convert.ToDateTime(reader["date_modified"]), + PatternId = Convert.ToInt32(reader["pattern_override_id"]) + }); + } + } + } + + return files; + } + + public void InsertNewFileRecord(List files, int profileId, int folderGroupId, string root) + { + var query = @"INSERT INTO main.file (full_path, name, size, date_created, date_modified, folder_root_id, profile_id, pattern_override_id) VALUES (@FullPath, @Name, @Size, @DateCreated, @DateModified, @FolderId, @ProfileId, @PatternId)"; + var rootLength = root.Length; + + using (var connection = new SqliteConnection(ConnectionString)) + { + connection.Open(); + using (var transaction = connection.BeginTransaction()) + { + + using (var command = new SqliteCommand(query, connection, transaction)) + { + foreach (var file in files) + { + command.Parameters.AddWithValue("FullPath", file.FullPath.Remove(0, rootLength)); + command.Parameters.AddWithValue("Name", file.Name); + command.Parameters.AddWithValue("Size", file.Size); + command.Parameters.AddWithValue("DateCreated", file.CreationDate); + command.Parameters.AddWithValue("DateModified", file.ModifiedDate); + command.Parameters.AddWithValue("FolderId", folderGroupId); + command.Parameters.AddWithValue("ProfileId", profileId); + command.Parameters.AddWithValue("PatternId", file.PatternId); + + command.ExecuteNonQuery(); + + command.Parameters.Clear(); + } + } + + transaction.Commit(); + } + } + } + public struct Profile { public string Name; @@ -371,5 +445,18 @@ namespace DataOrganizer public string ExampleText; public string Regex; } + + public struct FileSnapshot + { + public int Id; + public string FullPath; + public string Name; + public int ProfileId; + public int PatternId; + public int RootFolderId; + public DateTime CreationDate; + public DateTime ModifiedDate; + public long Size; + } } } diff --git a/DataOrganizer/DataOrganizer.csproj b/DataOrganizer/DataOrganizer.csproj index c25355b..88a67ca 100644 --- a/DataOrganizer/DataOrganizer.csproj +++ b/DataOrganizer/DataOrganizer.csproj @@ -99,6 +99,7 @@ + FileViewer.cs diff --git a/DataOrganizer/FileViewer.Designer.cs b/DataOrganizer/FileViewer.Designer.cs index fbeabbe..2ca4b6e 100644 --- a/DataOrganizer/FileViewer.Designer.cs +++ b/DataOrganizer/FileViewer.Designer.cs @@ -30,19 +30,19 @@ { this.MainMenu = new System.Windows.Forms.MenuStrip(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.SecondaryTreeView = new System.Windows.Forms.TreeView(); this.PrimaryFilesTreeView = new System.Windows.Forms.TreeView(); this.PanelOne = new System.Windows.Forms.Panel(); - this.label1 = new System.Windows.Forms.Label(); + this.ScanRootFolderButton = new System.Windows.Forms.Button(); + this.RootFolderComboBox = new System.Windows.Forms.ComboBox(); + this.label3 = new System.Windows.Forms.Label(); this.ProfileComboBox = new System.Windows.Forms.ComboBox(); - this.SecondaryTreeView = new System.Windows.Forms.TreeView(); + this.label1 = new System.Windows.Forms.Label(); this.SelectedFolderPanel = new System.Windows.Forms.Panel(); this.ActiveFolderGroupBox = new System.Windows.Forms.GroupBox(); - this.label2 = new System.Windows.Forms.Label(); - this.FolderSelectButton = new System.Windows.Forms.Button(); - this.label3 = new System.Windows.Forms.Label(); this.SelectedFolderComboBox = new System.Windows.Forms.ComboBox(); - this.RootFolderComboBox = new System.Windows.Forms.ComboBox(); - this.ScanRootFolderButton = new System.Windows.Forms.Button(); + this.FolderSelectButton = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); this.StatusStrip = new System.Windows.Forms.StatusStrip(); this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); this.tableLayoutPanel1.SuspendLayout(); @@ -83,9 +83,19 @@ this.tableLayoutPanel1.Size = new System.Drawing.Size(1472, 882); this.tableLayoutPanel1.TabIndex = 1; // + // SecondaryTreeView + // + this.SecondaryTreeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.SecondaryTreeView.Location = new System.Drawing.Point(739, 294); + this.SecondaryTreeView.Name = "SecondaryTreeView"; + this.tableLayoutPanel1.SetRowSpan(this.SecondaryTreeView, 2); + this.SecondaryTreeView.Size = new System.Drawing.Size(362, 585); + this.SecondaryTreeView.TabIndex = 2; + // // PrimaryFilesTreeView // this.PrimaryFilesTreeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.PrimaryFilesTreeView.FullRowSelect = true; this.PrimaryFilesTreeView.Location = new System.Drawing.Point(3, 294); this.PrimaryFilesTreeView.Name = "PrimaryFilesTreeView"; this.tableLayoutPanel1.SetRowSpan(this.PrimaryFilesTreeView, 2); @@ -106,14 +116,33 @@ this.PanelOne.Size = new System.Drawing.Size(362, 285); this.PanelOne.TabIndex = 1; // - // label1 + // ScanRootFolderButton // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(10, 20); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(104, 20); - this.label1.TabIndex = 0; - this.label1.Text = "Active Profile:"; + this.ScanRootFolderButton.Location = new System.Drawing.Point(186, 238); + this.ScanRootFolderButton.Name = "ScanRootFolderButton"; + this.ScanRootFolderButton.Size = new System.Drawing.Size(173, 44); + this.ScanRootFolderButton.TabIndex = 4; + this.ScanRootFolderButton.Text = "Scan Selected Folder"; + this.ScanRootFolderButton.UseVisualStyleBackColor = true; + this.ScanRootFolderButton.Click += new System.EventHandler(this.ScanRootFolderButton_Click); + // + // RootFolderComboBox + // + this.RootFolderComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.RootFolderComboBox.FormattingEnabled = true; + this.RootFolderComboBox.Location = new System.Drawing.Point(162, 57); + this.RootFolderComboBox.Name = "RootFolderComboBox"; + this.RootFolderComboBox.Size = new System.Drawing.Size(197, 28); + this.RootFolderComboBox.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(10, 60); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(146, 20); + this.label3.TabIndex = 2; + this.label3.Text = "Select Root Folder:"; // // ProfileComboBox // @@ -124,14 +153,14 @@ this.ProfileComboBox.Size = new System.Drawing.Size(239, 28); this.ProfileComboBox.TabIndex = 1; // - // SecondaryTreeView + // label1 // - this.SecondaryTreeView.Dock = System.Windows.Forms.DockStyle.Fill; - this.SecondaryTreeView.Location = new System.Drawing.Point(739, 294); - this.SecondaryTreeView.Name = "SecondaryTreeView"; - this.tableLayoutPanel1.SetRowSpan(this.SecondaryTreeView, 2); - this.SecondaryTreeView.Size = new System.Drawing.Size(362, 585); - this.SecondaryTreeView.TabIndex = 2; + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(10, 20); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(104, 20); + this.label1.TabIndex = 0; + this.label1.Text = "Active Profile:"; // // SelectedFolderPanel // @@ -156,14 +185,13 @@ this.ActiveFolderGroupBox.TabStop = false; this.ActiveFolderGroupBox.Text = "Folder Options"; // - // label2 + // SelectedFolderComboBox // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(6, 20); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(145, 20); - this.label2.TabIndex = 0; - this.label2.Text = "Folder to Compare:"; + this.SelectedFolderComboBox.FormattingEnabled = true; + this.SelectedFolderComboBox.Location = new System.Drawing.Point(157, 16); + this.SelectedFolderComboBox.Name = "SelectedFolderComboBox"; + this.SelectedFolderComboBox.Size = new System.Drawing.Size(509, 28); + this.SelectedFolderComboBox.TabIndex = 3; // // FolderSelectButton // @@ -175,41 +203,14 @@ this.FolderSelectButton.UseVisualStyleBackColor = true; this.FolderSelectButton.Click += new System.EventHandler(this.FolderSelectButton_Click); // - // label3 + // label2 // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(10, 60); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(146, 20); - this.label3.TabIndex = 2; - this.label3.Text = "Select Root Folder:"; - // - // SelectedFolderComboBox - // - this.SelectedFolderComboBox.FormattingEnabled = true; - this.SelectedFolderComboBox.Location = new System.Drawing.Point(157, 16); - this.SelectedFolderComboBox.Name = "SelectedFolderComboBox"; - this.SelectedFolderComboBox.Size = new System.Drawing.Size(509, 28); - this.SelectedFolderComboBox.TabIndex = 3; - // - // RootFolderComboBox - // - this.RootFolderComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.RootFolderComboBox.FormattingEnabled = true; - this.RootFolderComboBox.Location = new System.Drawing.Point(162, 57); - this.RootFolderComboBox.Name = "RootFolderComboBox"; - this.RootFolderComboBox.Size = new System.Drawing.Size(197, 28); - this.RootFolderComboBox.TabIndex = 3; - // - // ScanRootFolderButton - // - this.ScanRootFolderButton.Location = new System.Drawing.Point(186, 238); - this.ScanRootFolderButton.Name = "ScanRootFolderButton"; - this.ScanRootFolderButton.Size = new System.Drawing.Size(173, 44); - this.ScanRootFolderButton.TabIndex = 4; - this.ScanRootFolderButton.Text = "Scan Selected Folder"; - this.ScanRootFolderButton.UseVisualStyleBackColor = true; - this.ScanRootFolderButton.Click += new System.EventHandler(this.ScanRootFolderButton_Click); + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(6, 20); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(145, 20); + this.label2.TabIndex = 0; + this.label2.Text = "Folder to Compare:"; // // StatusStrip // diff --git a/DataOrganizer/FileViewer.cs b/DataOrganizer/FileViewer.cs index ce5414b..d659eb4 100644 --- a/DataOrganizer/FileViewer.cs +++ b/DataOrganizer/FileViewer.cs @@ -16,6 +16,7 @@ namespace DataOrganizer { private Dictionary Profiles { get; } = new Dictionary(); private Dictionary FolderGroups { get; } = new Dictionary(); + //private Dictionary Folders { get; } = new Dictionary(); public FileViewer() { @@ -31,10 +32,71 @@ namespace DataOrganizer } ProfileComboBox.SelectedIndexChanged += ProfileComboBox_SelectedIndexChanged; + RootFolderComboBox.SelectedIndexChanged += SelectedFolderComboBox_SelectedIndexChanged; ProfileComboBox.SelectedIndex = 0; } + private void SelectedFolderComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + var folder = FolderGroups[RootFolderComboBox.Text]; + var rootDepth = folder.Path.Split(new char[] { Path.DirectorySeparatorChar }).Length; + var profile = Profiles[ProfileComboBox.Text]; + var includedFolders = new Dictionary(); + var db = new DB(); + + PrimaryFilesTreeView.Nodes.Clear(); + + var files = db.GetFilesForProfileByFolderGroup(profile.Id, folder.Id); + var d = new Snapshot(files, profile, folder); + + var currentShowNode = new TreeNode(); + + foreach (var file in files) + { + var folders = file.FullPath.Split(new char[] { Path.DirectorySeparatorChar }); + var currentPath = folder.Path; + + if(folders.Length == rootDepth + 1) + { + PrimaryFilesTreeView.Nodes.Add(new TreeNode(folders[rootDepth]) { Name = Path.Combine(currentPath, folders[rootDepth]), ToolTipText = Path.Combine(currentPath, folders[rootDepth]) }); + continue; + } + + var previousPath = string.Empty; + + if (folders.Length >= rootDepth + 1) + { + if (currentShowNode.Text != folders[rootDepth]) + { + currentShowNode = new TreeNode(folders[rootDepth]) { Name = Path.Combine(currentPath, folders[rootDepth]), ToolTipText = Path.Combine(currentPath, folders[rootDepth]) }; + includedFolders.Add(Path.Combine(currentPath, folders[rootDepth]), currentShowNode); + PrimaryFilesTreeView.Nodes.Add(currentShowNode); + } + } + + for(var i = rootDepth; i < folders.Length - 1; i++) + { + previousPath = currentPath; + currentPath = Path.Combine(currentPath, folders[i]); + + if(!includedFolders.ContainsKey(currentPath)) + { + var newNode = new TreeNode(folders[i]) { Name = currentPath, ToolTipText = currentPath }; + + if (includedFolders.ContainsKey(previousPath)) + { + includedFolders[previousPath].Nodes.Add(newNode); + includedFolders.Add(currentPath, newNode); + } + } + } + + var node = includedFolders[currentPath]; + node.Nodes.Add(new TreeNode(folders[folders.Length - 1]) { Name = Path.Combine(currentPath, folders[folders.Length - 1]), ToolTipText = Path.Combine(currentPath, folders[folders.Length - 1]) }); + } + } + private void ProfileComboBox_SelectedIndexChanged(object sender, EventArgs e) { var profile = Profiles[ProfileComboBox.Text]; @@ -58,48 +120,67 @@ namespace DataOrganizer private void FolderSelectButton_Click(object sender, EventArgs e) { - var folder = FolderGroups[RootFolderComboBox.Text]; - var db = new DB(); + //var folder = FolderGroups[RootFolderComboBox.Text]; + //var profile = Profiles[ProfileComboBox.Text]; + //var db = new DB(); - StatusLabel.Text = $"{db.GetNamingPatternById(folder.PatternId)}"; - StatusStrip.Refresh(); + //StatusLabel.Text = $"{db.GetNamingPatternById(folder.PatternId)}"; + //StatusStrip.Refresh(); + + //PrimaryFilesTreeView.Nodes.Clear(); + + //var files = db.GetFilesForProfileByFolderGroup(profile.Id, folder.Id); + + //if (files.Count == 0) return; + + //var fileInfos = new List(); + + //foreach(var file in files) + //{ + // fileInfos.Add(new FileInfo(file.FullPath)); + //} } private void ScanRootFolderButton_Click(object sender, EventArgs e) { var folder = FolderGroups[RootFolderComboBox.Text]; - var db = new DB(); - var pattern = db.GetNamingPatternById(folder.PatternId); - var regex = new Regex(pattern); - PrimaryFilesTreeView.Nodes.Clear(); + //var db = new DB(); + //var pattern = db.GetNamingPatternById(folder.PatternId); + //var regex = new Regex(pattern); + //PrimaryFilesTreeView.Nodes.Clear(); - var dirs = Directory.EnumerateDirectories(folder.Path); + //var dirs = Directory.EnumerateDirectories(folder.Path); - foreach (var dir in dirs) - { - var dirInfo = new DirectoryInfo(dir); - PrimaryFilesTreeView.Nodes.Add(CreateNode(dirInfo, pattern)); - } + //foreach (var dir in dirs) + //{ + // var dirInfo = new DirectoryInfo(dir); + // PrimaryFilesTreeView.Nodes.Add(CreateNode(dirInfo, pattern)); + //} - foreach(var file in Directory.EnumerateFiles(folder.Path)) - { - var fileInfo = new FileInfo(file); - var fileNode = new TreeNode(fileInfo.Name) { Name = fileInfo.FullName }; + //foreach(var file in Directory.EnumerateFiles(folder.Path)) + //{ + // var fileInfo = new FileInfo(file); + // var fileNode = new TreeNode(fileInfo.Name) { Name = fileInfo.FullName }; - if (!regex.IsMatch(fileInfo.Name)) - { - fileNode.ForeColor = Color.DarkOrange; - } + // if (!regex.IsMatch(fileInfo.Name)) + // { + // fileNode.ForeColor = Color.DarkOrange; + // } - PrimaryFilesTreeView.Nodes.Add(fileNode); - } + // PrimaryFilesTreeView.Nodes.Add(fileNode); + //} + + WriteFilesToDb(folder.Path); } private TreeNode CreateNode(DirectoryInfo dir, string pattern) { + var folder = FolderGroups[RootFolderComboBox.Text]; + var profile = Profiles[ProfileComboBox.Text]; var namingViolation = false; var node = new TreeNode(dir.Name) { Name = dir.FullName }; var regex = new Regex(pattern); + var db = new DB(); var files = Directory.EnumerateFiles(dir.FullName); @@ -122,15 +203,16 @@ namespace DataOrganizer } node.Nodes.Add(fileNode); + db.InsertNewFileRecord(GetFileSnapshots(dir.FullName), profile.Id, folder.Id, folder.Path); } if (namingViolation) node.ForeColor = Color.DarkOrange; var dirs = Directory.EnumerateDirectories(dir.FullName); - foreach(var folder in dirs) + foreach(var f in dirs) { - var child = CreateNode(new DirectoryInfo(folder), pattern); + var child = CreateNode(new DirectoryInfo(f), pattern); node.ForeColor = child.ForeColor; node.Nodes.Add(child); } @@ -138,9 +220,75 @@ namespace DataOrganizer return node; } - private struct Folder + private void WriteFilesToDb(string root) { + var dir = new DirectoryInfo(root); + var folder = FolderGroups[RootFolderComboBox.Text]; + var profile = Profiles[ProfileComboBox.Text]; + //var db = new DB(); + //var pattern = db.GetNamingPatternById(folder.PatternId); + WriteFilesInFolderToDb(dir.FullName, profile.Id, folder.Id, root); + UpdateStatusStrip("Finished processing files."); + } + + private void WriteFilesInFolderToDb(string path, int profileId, int folderId, string root) + { + var dir = new DirectoryInfo(path); + var db = new DB(); + + var files = GetFileSnapshots(dir.FullName); + + if(files.Count > 0 ) db.InsertNewFileRecord(files, profileId, folderId, root); + + foreach(var d in dir.EnumerateDirectories()) + { + UpdateStatusStrip($"Processing {d.FullName}"); + + WriteFilesInFolderToDb(d.FullName, profileId, folderId, root); + } + } + + private List GetFileSnapshots(string path) + { + var dir = new DirectoryInfo(path); + var profile = GetCurrentProfile(); + var folderGroup = GetCurrentFolderGroup(); + + var snapshots = new List(); + + foreach(var file in dir.EnumerateFiles()) + { + snapshots.Add(new DB.FileSnapshot + { + FullPath = file.FullName, + Name = file.Name, + CreationDate = file.CreationTimeUtc, + ModifiedDate = file.LastWriteTimeUtc, + ProfileId = profile.Id, + RootFolderId = folderGroup.Id, + Size = file.Length, + PatternId = 0 //TODO: Add something that let's the user override the global pattern. + }); + } + + return snapshots; + } + + private DB.Profile GetCurrentProfile() + { + return Profiles[ProfileComboBox.Text]; + } + + private DB.FolderGroup GetCurrentFolderGroup() + { + return FolderGroups[RootFolderComboBox.Text]; + } + + private void UpdateStatusStrip(string message) + { + StatusLabel.Text = message; + StatusStrip.Refresh(); } } } diff --git a/DataOrganizer/Snapshot.cs b/DataOrganizer/Snapshot.cs new file mode 100644 index 0000000..e46fb05 --- /dev/null +++ b/DataOrganizer/Snapshot.cs @@ -0,0 +1,83 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DataOrganizer +{ + class Snapshot + { + public Folder Root { get; private set; } + public Dictionary Files { get; private set; } = new Dictionary(); + public Dictionary Directories { get; private set; } = new Dictionary(); + + public Snapshot(List fileRecords, DB.Profile profile, DB.FolderGroup folderGroup) + { + Root = new Folder(folderGroup.Name, folderGroup.Path); + Directories.Add(Root.FullPath, Root); + + var rootDepth = folderGroup.Path.Split(new char[] { Path.DirectorySeparatorChar }).Length; + + foreach (var file in fileRecords) + { + var folders = file.FullPath.Split(new char[] { Path.DirectorySeparatorChar }); + var currentPath = folderGroup.Path; + + if (folders.Length == rootDepth + 1) + { + Root.AddFile(file); + Files.Add(file.FullPath, file); + continue; + } + + for (var i = rootDepth; i < folders.Length - 1; i++) + { + string previousPath = currentPath; + currentPath = Path.Combine(currentPath, folders[i]); + + if (!Directories.ContainsKey(currentPath)) + { + var newFolder = new Folder(folders[i], currentPath); + Directories[previousPath].AddDirectory(newFolder); + Directories.Add(currentPath, newFolder); + } + } + + Directories[currentPath].AddFile(file); + } + } + } + + public class Folder + { + public string Name { get; private set; } + public string FullPath { get; private set; } + public Dictionary Files { get; private set; } = new Dictionary(); + public Dictionary Folders { get; private set; } = new Dictionary(); + public List Duplicates { get; private set; } + + public Folder(string name, string fullPath) + { + Name = name; + FullPath = fullPath; + } + + public void AddFile(DB.FileSnapshot file) + { + Files.Add(file.FullPath, file); + } + + public void AddDirectory(Folder folder) + { + Folders.Add(folder.FullPath, folder); + } + + public struct Duplicate + { + DB.FileSnapshot FileA; + DB.FileSnapshot FileB; + } + } +}