using System; using System.IO; using System.Xml.Serialization; using System.Linq; using System.Collections.ObjectModel; namespace TapeCatalog.Methods { /// /// Simple settings container and load/save helpers. /// [Serializable] public class SettingsData { public string SourceDirectory { get; set; } public string ArchiveDirectory { get; set; } public string XmlDirectory { get; set; } public static SettingsData Default => new SettingsData { SourceDirectory = string.Empty, ArchiveDirectory = string.Empty, XmlDirectory = string.Empty }; } public static class SettingsManager { private const string DefaultFileName = "appsettings.xml"; public static void Save(SettingsData data, string filePath = null) { if (data == null) throw new ArgumentNullException(nameof(data)); var path = string.IsNullOrWhiteSpace(filePath) ? DefaultFileName : filePath; try { using (var fs = File.Create(path)) { var ser = new XmlSerializer(typeof(SettingsData)); ser.Serialize(fs, data); } } catch { // swallow errors; callers can handle existence/permission issues } } public static SettingsData Load(string filePath = null) { var path = string.IsNullOrWhiteSpace(filePath) ? DefaultFileName : filePath; if (!File.Exists(path)) return SettingsData.Default; try { using (var fs = File.OpenRead(path)) { var ser = new XmlSerializer(typeof(SettingsData)); return ser.Deserialize(fs) as SettingsData ?? SettingsData.Default; } } catch { return SettingsData.Default; } } } // UI-related helpers used by the Settings tab. These methods avoid direct UI manipulation // and return data so the MainWindow can update controls. public static class SettingsUi { public static string SelectDirectory(string description) { using (var dlg = new System.Windows.Forms.FolderBrowserDialog()) { dlg.Description = description ?? "Select a folder"; dlg.ShowNewFolderButton = true; var result = dlg.ShowDialog(); if (result == System.Windows.Forms.DialogResult.OK && !string.IsNullOrWhiteSpace(dlg.SelectedPath)) return dlg.SelectedPath; } return null; } public static int ScanSource(string path, ObservableCollection files) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (!Directory.Exists(path)) throw new DirectoryNotFoundException(path); // normalize source root for reliable relative path calculation var rootFull = System.IO.Path.GetFullPath(path).TrimEnd(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar); foreach (var file in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories)) { try { var fi = new FileInfo(file); // compute directory relative to source root (remove the source root prefix) var dirFull = System.IO.Path.GetFullPath(fi.DirectoryName).TrimEnd(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar); string relativeDir = string.Empty; if (dirFull.StartsWith(rootFull, StringComparison.OrdinalIgnoreCase)) relativeDir = dirFull.Length == rootFull.Length ? string.Empty : dirFull.Substring(rootFull.Length).TrimStart(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar); else relativeDir = fi.DirectoryName; var existing = files.FirstOrDefault(f => string.Equals(f.Filename, fi.Name, StringComparison.OrdinalIgnoreCase) && string.Equals(f.FileDir, relativeDir, StringComparison.OrdinalIgnoreCase)); if (existing != null) { var newSizeMb = FormatBytesToMb(fi.Length); if (existing.SizeSrc != newSizeMb) { existing.SizeSrc = newSizeMb; existing.ModSrc = fi.LastWriteTime.ToString(); existing.Status = string.Empty; existing.ArcDrive = string.Empty; } } else { files.Add(new TapeCatalog.FileEntry { Filename = fi.Name, FileDir = relativeDir, SizeSrc = FormatBytesToMb(fi.Length), ModSrc = fi.LastWriteTime.ToString(), }); } } catch { // ignore inaccessible files } } return files.Count; } public static int ScanArchive(string path, ObservableCollection files) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (!Directory.Exists(path)) throw new DirectoryNotFoundException(path); // normalize archive root for reliable relative path calculation var rootFull = System.IO.Path.GetFullPath(path).TrimEnd(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar); foreach (var file in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories)) { try { var fi = new FileInfo(file); var dirFull = System.IO.Path.GetFullPath(fi.DirectoryName).TrimEnd(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar); string relativeDir = string.Empty; if (dirFull.StartsWith(rootFull, StringComparison.OrdinalIgnoreCase)) relativeDir = dirFull.Length == rootFull.Length ? string.Empty : dirFull.Substring(rootFull.Length).TrimStart(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar); else relativeDir = fi.DirectoryName; var existing = files.FirstOrDefault(f => string.Equals(f.Filename, fi.Name, StringComparison.Ordinal) && string.Equals(f.FileDir, relativeDir, StringComparison.OrdinalIgnoreCase)); if (existing != null) { existing.SizeArc = FormatBytesToMb(fi.Length); DateTime prevMod; if (!DateTime.TryParse(existing.ModArc, out prevMod)) prevMod = DateTime.MinValue; var mod = fi.LastWriteTime > prevMod ? fi.LastWriteTime : prevMod; existing.ModArc = mod.ToString(); } else { files.Add(new TapeCatalog.FileEntry { Filename = fi.Name, FileDir = relativeDir, SizeArc = FormatBytesToMb(fi.Length), ModArc = fi.LastWriteTime.ToString() }); } } catch { // ignore inaccessible files } } return files.Count; } public static string[] GetXmlFiles(string xmlPath) { if (string.IsNullOrWhiteSpace(xmlPath) || !Directory.Exists(xmlPath)) return new string[0]; try { return Directory.GetFiles(xmlPath, "*.xml", SearchOption.TopDirectoryOnly); } catch { return new string[0]; } } private static string FormatBytesToMb(long bytes) { double mb = bytes / 1024.0 / 1024.0; return mb.ToString("F2"); } } }