diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..986a9fe
Binary files /dev/null and b/.DS_Store differ
diff --git a/._.DS_Store b/._.DS_Store
new file mode 100644
index 0000000..4943dd3
Binary files /dev/null and b/._.DS_Store differ
diff --git a/.gitignore b/.gitignore
index dbd545c..900cc1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,4 @@
/WpfApp/obj
/App.WPF
/WpfApp/bin/Debug/net8.0-windows
+/._.gitignore
diff --git a/App.Cmd/ViewModels/SaveViewModel.cs b/App.Cmd/ViewModels/SaveViewModel.cs
index 2c27d10..1e4d4ee 100644
--- a/App.Cmd/ViewModels/SaveViewModel.cs
+++ b/App.Cmd/ViewModels/SaveViewModel.cs
@@ -1,6 +1,7 @@
using App.Core.Models;
using App.Core.Services;
using Newtonsoft.Json;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Text.RegularExpressions;
@@ -15,6 +16,7 @@ public partial class SaveViewModel
private readonly LoggerService? loggerService;
private readonly CopyService? copyService;
private readonly DisplayService displayService;
+ private ThreadManagerService threadManagerService = new();
[GeneratedRegex(@"^\d+;\d+$")]
private static partial Regex MyRegex();
@@ -32,7 +34,8 @@ public SaveViewModel()
};
loggerService = new();
- copyService = new(stateManagerService);
+ copyService = new();
+ copyService.stateManagerService = stateManagerService;
displayService = new();
saveService = new()
@@ -46,21 +49,12 @@ public SaveViewModel()
saveService.ListStateManager = listState;
}
-
-
-
public enum TypeOfSave
{
Sequential,
Complete
}
-
- ///
- /// Method to get the user choice
- ///
- ///
- ///
public bool UserChoice(int UserEntry)
{
saveService!.ListSaveModel = ListSaveModel;
@@ -215,7 +209,7 @@ public bool UserChoice(int UserEntry)
saveService!.CreateSave( InPath, OutPath, type, SaveName);
- stateManagerService!.UpdateStateFile();
+ //stateManagerService!.UpdateStateFile();
ListSaveModel = saveService.ListSaveModel;
listState = stateManagerService!.listStateModel!;
@@ -262,57 +256,45 @@ public bool UserChoice(int UserEntry)
{
if (!saveService!.IsSoftwareRunning())
{
-
+ List list = new List();
string[] parts = UserChoice.Split(';');
int z1 = int.Parse(parts[0]);
int z2 = int.Parse(parts[1]);
- DisplayService.SetForegroundColor("Green", $"Save {z1} is running");
-
- saveService!.ExecuteSave(ListSaveModel[z1]);
- DisplayService.SetForegroundColor("Green", $"Save {z1} Executed");
- Thread.Sleep(1000);
- DisplayService.SetForegroundColor("Green", $"Save {z2} is running");
- saveService!.ExecuteSave(ListSaveModel[z2]);
- DisplayService.SetForegroundColor("Green", $"Save {z2} Executed");
- Thread.Sleep(1000);
-
-
+ Console.WriteLine();
+ list.Add(ListSaveModel[z1]);
+ list.Add(ListSaveModel[z2]);
+ saveService!.ExecuteSave(list, threadManagerService);
}
else
{
DisplayService.SetBackForeColor("Black", "DarkRed", "Software is running save cannot be executed...");
System.Threading.Thread.Sleep(1500);
}
-
}
else
{
//TODO : Ajouter un try catch pour la gestion des entrées de l'utilisateur
if (!saveService!.IsSoftwareRunning())
{
+ List list = new List();
string[] parts = UserChoice.Split('-');
int min = int.Parse(parts[0]);
int max = int.Parse(parts[1]);
for (int x = min; x <= max; x++)
{
- DisplayService.SetForegroundColor("Green", $"Save {x} is running");
- saveService!.ExecuteSave(ListSaveModel[x]);
- DisplayService.SetForegroundColor("Green", $"Save {x} Executed");
- Thread.Sleep(1000);
+ list.Add(ListSaveModel[x]);
}
-
+ saveService!.ExecuteSave(list, threadManagerService);
}
else
{
DisplayService.SetBackForeColor("Black", "DarkRed", "Software is running save cannot be executed...");
System.Threading.Thread.Sleep(1500);
}
-
-
}
- //return true;
- }
+ }
+
catch (ArgumentOutOfRangeException)
{
//TODO : Quand save est vide
@@ -355,15 +337,21 @@ public bool UserChoice(int UserEntry)
}
}
+ private void SaveViewModel_CopyPaused(object? sender, EventArgs e)
+ {
+ Console.WriteLine("Save Paused");
+ }
-
-
+ private void SaveViewModel_CopyStopped(object? sender, EventArgs e)
+ {
+ Console.WriteLine("Save Stopped");
+ }
public void ShowLogs()
{
//Method to show the logs
- loggerService.OpenLogFile();
+ loggerService?.OpenLogFile();
}
///
@@ -384,17 +372,17 @@ public void ShowSavesSchedule()
{
FileInfo fileInfo = new("saves.json");
- if (fileInfo.Length > 0)
- {
- string json = File.ReadAllText("saves.json");
- ListSaveModel = JsonConvert.DeserializeObject>(json) ?? [];
+ if (fileInfo.Length > 0)
+ {
+ string json = File.ReadAllText("saves.json");
+ ListSaveModel = JsonConvert.DeserializeObject>(json) ?? [];
+ }
+ else
+ {
+ // Fichier vide, initialiser la liste sans désérialiser
+ ListSaveModel = [];
+ }
}
- else
- {
- // Fichier vide, initialiser la liste sans désérialiser
- ListSaveModel = [];
- }
- }
else
{
// Créer le fichier s'il n'existe pas
@@ -406,7 +394,7 @@ public void ShowSavesSchedule()
foreach (SaveModel item in ListSaveModel)
{
- Console.WriteLine($"{i} "+saveService!.ShowInfo(item));
+ Console.WriteLine($"{i} "+saveService!.ShowInfo(item) + threadManagerService.AreThreadsRunning(i));
i++;
}
diff --git a/App.Core/Models/ConfigModel.cs b/App.Core/Models/ConfigModel.cs
deleted file mode 100644
index a1c8cd2..0000000
--- a/App.Core/Models/ConfigModel.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using App.Core.Services;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Configuration;
-
-namespace App.Core.Models
-{
- public class ConfigModel
- {
-
- }
-}
diff --git a/App.Core/Models/CopyModel.cs b/App.Core/Models/CopyModel.cs
index f4d3307..7925634 100644
--- a/App.Core/Models/CopyModel.cs
+++ b/App.Core/Models/CopyModel.cs
@@ -1,11 +1,14 @@
+using System.ComponentModel;
+
namespace App.Core.Models
{
- public class CopyModel
+ public class CopyModel : INotifyPropertyChanged
{
public string SourcePath { get; set; } = string.Empty; // Path of the source file
public string TargetPath { get; set; } = string.Empty; // Path of the target file
+ public event PropertyChangedEventHandler? PropertyChanged;
}
}
diff --git a/App.Core/Models/LoggerModel.cs b/App.Core/Models/LoggerModel.cs
index ca60ee8..2599988 100644
--- a/App.Core/Models/LoggerModel.cs
+++ b/App.Core/Models/LoggerModel.cs
@@ -1,6 +1,8 @@
-namespace App.Core.Models
+using System.ComponentModel;
+
+namespace App.Core.Models
{
- public class LoggerModel
+ public class LoggerModel : INotifyPropertyChanged
{
public string Name { get; set; } = string.Empty; // Name of the save
public string FileSource { get; set; } = string.Empty; // Path of the source file
@@ -9,5 +11,7 @@ public class LoggerModel
public string FileTransferTime { get; set; } = string.Empty; // Time of the transfer
public string FileEncryptionTime { get; set; } = string.Empty; // Time of the encryption
public DateTime Time { get; set; } = DateTime.Now; // Date of the save
+
+ public event PropertyChangedEventHandler? PropertyChanged;
}
}
diff --git a/App.Core/Models/SaveModel.cs b/App.Core/Models/SaveModel.cs
index ec17d61..366918a 100644
--- a/App.Core/Models/SaveModel.cs
+++ b/App.Core/Models/SaveModel.cs
@@ -1,12 +1,37 @@
-namespace App.Core.Models
+using System;
+using System.ComponentModel;
+
+namespace App.Core.Models
{
- public class SaveModel
+ public class SaveModel : INotifyPropertyChanged
{
- public string InPath { get; set; } = ""; // Path of the source file
- public string OutPath { get; set; } = ""; // Path of the target file
- public string Type { get; set; } = ""; // Type of the save // false = Complete, true = Sequentiel
- public string SaveName { get; set; } = "" ; // Name of the save
+ private int _percentage;
+
+ public string InPath { get; set; } = ""; // Path of the source file
+ public string OutPath { get; set; } = ""; // Path of the target file
+ public string Type { get; set; } = ""; // Type of the save (false = Complete, true = Sequential)
+ public string SaveName { get; set; } = ""; // Name of the save
public string EncryptChoice { get; set; } = "";
- public DateTime Date { get; } = DateTime.Now; // Date of the save
+ public DateTime Date { get; } = DateTime.Now; // Date of the save
+
+ public float percentage
+ {
+ get { return _percentage; }
+ set
+ {
+ if (_percentage != value)
+ {
+ _percentage = (int)value;
+ OnPropertyChanged(nameof(percentage));
+ }
+ }
+ }
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
}
}
diff --git a/App.Core/Models/StateManagerModel.cs b/App.Core/Models/StateManagerModel.cs
index d32e3c7..3e1c3c5 100644
--- a/App.Core/Models/StateManagerModel.cs
+++ b/App.Core/Models/StateManagerModel.cs
@@ -1,7 +1,9 @@
-namespace App.Core.Models
+using System.ComponentModel;
+
+namespace App.Core.Models
{
- public class StateManagerModel
+ public class StateManagerModel : INotifyPropertyChanged
{
public string SaveName { get; set; } = string.Empty; // Name of the save
public string SourceFilePath { get; set; } = string.Empty; // Path of the source file
@@ -12,5 +14,6 @@ public class StateManagerModel
public long NbFilesLeftToDo { get; set; } = 0; // Number of files left to copy
public float Progression { get; set; } = 0; // Progression of the save
+ public event PropertyChangedEventHandler? PropertyChanged;
}
}
diff --git a/App.Core/Services/CopyService.cs b/App.Core/Services/CopyService.cs
index c6e05ca..d9a4fa3 100644
--- a/App.Core/Services/CopyService.cs
+++ b/App.Core/Services/CopyService.cs
@@ -1,62 +1,58 @@
using App.Core.Models;
using System.Diagnostics;
+using System.Drawing;
using System.IO;
using System.Threading;
namespace App.Core.Services
{
- public class CopyService
+ public class CopyService
{
public LoggerService loggerService = new();
public StateManagerService stateManagerService = new();
- private bool isStopped;
- private bool isPaused;
public bool isEncrypted;
- private long totalFile = 0;
- private long totalSize = 0;
- private float progress =0;
+ private readonly object locker = new();
public CopyModel CopyModel { get; set; }
+ public event EventHandler? BackupStarted;
+ public event EventHandler? BackupCompleted;
+
+
+
public CopyService()
{
this.CopyModel = new();
}
- public CopyService(StateManagerService stateManagerService)
- {
- this.CopyModel = new();
- this.stateManagerService = stateManagerService;
- }
- public void ExecuteCopy(SaveModel saveModel)
+ public void ExecuteCopy(SaveModel saveModel, StreamWriter logWriter, StreamWriter stateWriter)
{
- isPaused = false;
- isStopped = false;
- totalFile = 0;
- totalSize = 0;
- ProcessCopy(saveModel);
+
+ Thread thread = new Thread(() =>
+ {
+ OnBackupStarted(saveModel);
+ BackupDirectory(saveModel.InPath, saveModel.OutPath, logWriter, stateWriter);
+ OnBackupCompleted(saveModel);
+ });
+ thread.Start();
+
}
- public void PauseCopy(SaveModel saveModel)
+ public void PauseCopy()
{
- isPaused = true;
- // Implement any necessary logic for pausing the copying process
}
- public void StopCopy(SaveModel saveModel)
+ public void ResumeCopy()
{
- isStopped = true;
- // Implement any necessary logic for stopping the copying process
+
}
- public void ResumeCopy(SaveModel saveModel)
+ public void StopCopy()
{
- isPaused = false;
- // Implement any necessary logic for resuming the copying process
- ProcessCopy(saveModel);
}
+
private void EncryptFile(string sourcePath)
{
string additionalArgument = "abcabcab";
@@ -69,138 +65,395 @@ private void EncryptFile(string sourcePath)
Process.Start(startInfo);
}
-
- private void ProcessCopy(SaveModel saveModel)
+ void BackupDirectory(string sourceDirPath, string targetDirPath, StreamWriter logWriter, StreamWriter stateWriter)
{
- if (isPaused || isStopped)
- return;
+ while (true)
+ { // Wait until manualReset is set
- foreach (var item in Directory.GetFiles(this.CopyModel.SourcePath, "*", SearchOption.AllDirectories))
- {
- totalFile += 1;
- totalSize += new FileInfo(item).Length;
- }
-
- foreach (StateManagerModel stateModel in stateManagerService.listStateModel!)
- {
- if (stateModel.SaveName == saveModel.SaveName)
+ int TotalFailed = 0;
+ // Stage 1: Create the destination folder
+ if (!Directory.Exists(targetDirPath))
{
-
- stateModel.TotalFilesToCopy += totalFile;
- stateModel.NbFilesLeftToDo = totalFile;
- stateModel.TotalFilesSize = totalSize;
- stateModel.Progression = 100 - ((stateModel.NbFilesLeftToDo / totalFile) * 100);
- progress = stateModel.Progression;
- stateModel.State = "ACTIVE";
- stateManagerService.UpdateStateFile();
-
- if (File.Exists(this.CopyModel.SourcePath))
+ try
{
- // File copying operation
-
- stateModel.SourceFilePath = this.CopyModel.SourcePath;
- stateModel.TargetFilePath = this.CopyModel.TargetPath;
- stateManagerService.UpdateStateFile();
-
-
+ Directory.CreateDirectory(targetDirPath);
+ logWriter.WriteLine($"Create folder: {targetDirPath}");
+ }
+ catch (Exception ex)
+ {
+ // Cannot create folder
+ stateWriter.WriteLine($"Failed to create folder: {targetDirPath}\r\nAccess Denied\r\n");
+ return;
+ }
+ }
- File.Copy(this.CopyModel.SourcePath, this.CopyModel.TargetPath, true);
- stateModel.Progression = 100 - ((stateModel.NbFilesLeftToDo / totalFile) * 100);
- progress = stateModel.Progression;
- stateModel.NbFilesLeftToDo = stateModel.NbFilesLeftToDo > 0 ? stateModel.NbFilesLeftToDo - 1 : 0;
+ // Stage 2: Get all files from the source folder
+ string[] files = null;
+ try
+ {
+ files = Directory.GetFiles(sourceDirPath);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ // Access denied, cannot read folder or files
+ stateWriter.WriteLine($"{sourceDirPath}\r\nAccess Denied\r\n");
+ }
+ catch (Exception e)
+ {
+ // Other unknown read errors
+ stateWriter.WriteLine($"{sourceDirPath}\r\n{e.Message}\r\n");
+ }
- stateManagerService.UpdateStateFile();
+ // Stage 3: Copy all files from source to destination folder
+ if (files != null && files.Length > 0)
+ {
+ foreach (string file in files)
+ {
+ try
+ {
+ string name = Path.GetFileName(file);
+ string dest = Path.Combine(targetDirPath, name);
+
+ File.Copy(file, dest, true);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ // Access denied, cannot write file
+ stateWriter.WriteLine($"{file}\r\nAccess Denied\r\n");
+ TotalFailed++;
+ }
+ catch (Exception e)
+ {
+ // Other unknown error
+ TotalFailed++;
+ stateWriter.WriteLine($"{file}\r\n{e.Message}\r\n");
+ }
+ }
+ }
- loggerService!.loggerModel!.Name = saveModel.SaveName;
- loggerService.loggerModel.FileSource = this.CopyModel.SourcePath;
- loggerService.loggerModel.FileTarget = this.CopyModel.TargetPath;
- loggerService.loggerModel.FileSize = new FileInfo(this.CopyModel.SourcePath).Length.ToString();
- loggerService.AddEntryLog();
+ // Stage 4: Get all sub-folders
+ string[] folders = null;
+ try
+ {
+ folders = Directory.GetDirectories(sourceDirPath);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ // Access denied, cannot read folders
+ stateWriter.WriteLine($"{sourceDirPath}\r\nAccess denied\r\n");
+ }
+ catch (Exception e)
+ {
+ // Other unknown read errors
+ stateWriter.WriteLine($"{sourceDirPath}\r\nAccess {e.Message}\r\n");
+ }
- }
- else if (Directory.Exists(this.CopyModel.SourcePath))
+ // Stage 5: Backup files and "sub-sub-folders" in the sub-folder
+ if (folders != null && folders.Length > 0)
+ {
+ foreach (string folder in folders)
{
- // Directory copying operation
- CopyDirectory(this.CopyModel.SourcePath, this.CopyModel.TargetPath, stateModel);
+ try
+ {
+ string name = Path.GetFileName(folder);
+ string dest = Path.Combine(targetDirPath, name);
+
+ // recursive call with updated source and target paths
+ BackupDirectory(folder, dest, logWriter, stateWriter);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ // Access denied, cannot read folders
+ stateWriter.WriteLine($"{folder}\r\nAccess denied\r\n");
+ }
+ catch (Exception e)
+ {
+ // Other unknown read errors
+ stateWriter.WriteLine($"{targetDirPath}\r\nAccess {e.Message}\r\n");
+ }
}
- else
- {
- // Log the error and handle it gracefully
- loggerService!.loggerModel!.Name = saveModel.SaveName;
- loggerService.AddEntryLog();
- }
-
-
+ }
- stateModel.State = "END";
- stateManagerService.UpdateStateFile();
+ // Perform encryption if required
+ if (this.isEncrypted)
+ {
+ EncryptFile(this.CopyModel.TargetPath);
}
+
+
}
-
-
- if (isEncrypted) EncryptFile(this.CopyModel.TargetPath);
-
-
}
- private void CopyDirectory(string sourceDirPath, string targetDirPath, StateManagerModel stateModel)
- {
-
- // Vérifie si le répertoire source existe
- if (!Directory.Exists(sourceDirPath))
+ //public void CompleteSave(string inputpathsave, string inputDestToSave, bool copyDir, bool verif) //Function for full folder backup
+ //{
+ // StateManagerModel stateModel = new StateManagerModel();
+ // stateModel.State = "ACTIVE";
+ // Stopwatch stopwatch = new Stopwatch();
+ // Stopwatch cryptwatch = new Stopwatch();
+ // stopwatch.Start(); //Starting the timed for the log file
+
+ // DirectoryInfo dir = new DirectoryInfo(inputpathsave); // Get the subdirectories for the specified directory.
+
+ // if (!dir.Exists) //Check if the file is present
+ // {
+ // throw new DirectoryNotFoundException("ERROR 404 : Directory Not Found ! " + inputpathsave);
+ // }
+
+ // DirectoryInfo[] dirs = dir.GetDirectories();
+ // Directory.CreateDirectory(inputDestToSave); // If the destination directory doesn't exist, create it.
+
+ // FileInfo[] files = dir.GetFiles(); // Get the files in the directory and copy them to the new location.
+
+ // if (!verif) // Check for the status file if it needs to reset the variables
+ // {
+ // TotalSize = 0;
+ // nbfilesmax = 0;
+ // size = 0;
+ // nbfiles = 0;
+ // progs = 0;
+
+ // foreach (FileInfo file in files) // Loop to allow calculation of files and folder size
+ // {
+ // TotalSize += file.Length;
+ // nbfilesmax++;
+ // }
+ // foreach (DirectoryInfo subdir in dirs) // Loop to allow calculation of subfiles and subfolder size
+ // {
+ // FileInfo[] Maxfiles = subdir.GetFiles();
+ // foreach (FileInfo file in Maxfiles)
+ // {
+ // TotalSize += file.Length;
+ // nbfilesmax++;
+ // }
+ // }
+
+ // }
+
+ // Loop that allows to copy the files to make the backup
+ // foreach (FileInfo file in files)
+ // {
+ // if (this.button_pause == true)
+ // {
+ // MessageBox.Show("test");
+ // }
+ // if (this.button_stop == true)
+ // {
+ // Thread.ResetAbort();
+ // }
+
+ // string tempPath = Path.Combine(inputDestToSave, file.Name);
+
+ // if (size > 0)
+ // {
+ // progs = ((float)size / TotalSize) * 100;
+ // }
+
+ // Systems which allows to insert the values of each file in the report file.
+ // DataState.SourceFile = Path.Combine(inputpathsave, file.Name);
+ // DataState.TargetFile = tempPath;
+ // DataState.TotalSize = nbfilesmax;
+ // DataState.TotalFile = TotalSize;
+ // DataState.TotalSizeRest = TotalSize - size;
+ // DataState.FileRest = nbfilesmax - nbfiles;
+ // DataState.Progress = progs;
+ // UpdateStatefile(); //Call of the function to start the state file system
+
+ // if (PriorityExt(Path.GetExtension(file.Name)))
+ // {
+ // if (CryptExt(Path.GetExtension(file.Name)))
+ // {
+ // cryptwatch.Start();
+ // Encrypt(DataState.SourceFile, tempPath);
+ // cryptwatch.Stop();
+ // }
+ // else
+ // {
+ // file.CopyTo(tempPath, true); //Function that allows you to copy the file to its new folder.
+ // }
+
+ // }
+ // else
+ // {
+ // if (CryptExt(Path.GetExtension(file.Name)))
+ // {
+ // cryptwatch.Start();
+ // Encrypt(DataState.SourceFile, tempPath);
+ // cryptwatch.Stop();
+ // }
+ // else
+ // {
+ // file.CopyTo(tempPath, true); //Function that allows you to copy the file to its new folder.
+ // }
+ // }
+
+ // nbfiles++;
+ // size += file.Length;
+
+ // }
+
+ // If copying subdirectories, copy them and their contents to new location.
+ // if (copyDir)
+ // {
+ // foreach (DirectoryInfo subdir in dirs)
+ // {
+ // string tempPath = Path.Combine(inputDestToSave, subdir.Name);
+ // CompleteSave(subdir.FullName, tempPath, copyDir, true);
+ // }
+ // }
+ // System which allows the values to be reset to 0 at the end of the backup
+ // DataState.TotalSize = TotalSize;
+ // DataState.SourceFile = null;
+ // DataState.TargetFile = null;
+ // DataState.TotalFile = 0;
+ // DataState.TotalSize = 0;
+ // DataState.TotalSizeRest = 0;
+ // DataState.FileRest = 0;
+ // DataState.Progress = 0;
+ // DataState.SaveState = false;
+
+ // UpdateStatefile(); //Call of the function to start the state file system
+
+ // stopwatch.Stop(); //Stop the stopwatch
+ // cryptwatch.Stop();
+ // this.TimeTransfert = stopwatch.Elapsed; // Transfer of the chrono time to the variable
+ // this.CryptTransfert = cryptwatch.Elapsed;
+ //}
+
+ //public void DifferentialSave(string pathA, string pathB, string pathC) // Function that allows you to make a differential backup
+ //{
+ // DataState = new DataState(NameStateFile); //Instattation of the method
+ // Stopwatch stopwatch = new Stopwatch(); // Instattation of the method
+ // Stopwatch cryptwatch = new Stopwatch();
+ // stopwatch.Start(); //Starting the stopwatch
+
+ // DataState.SaveState = true;
+ // TotalSize = 0;
+ // nbfilesmax = 0;
+
+ // System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo(pathA);
+ // System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo(pathB);
+
+ // Take a snapshot of the file system.
+ // IEnumerable list1 = dir1.GetFiles("*.*", System.IO.SearchOption.AllDirectories);
+ // IEnumerable list2 = dir2.GetFiles("*.*", System.IO.SearchOption.AllDirectories);
+
+ // A custom file comparer defined below
+ // FileCompare myFileCompare = new FileCompare();
+
+ // var queryList1Only = (from file in list1 select file).Except(list2, myFileCompare);
+ // size = 0;
+ // nbfiles = 0;
+ // progs = 0;
+
+ // foreach (var v in queryList1Only)
+ // {
+ // TotalSize += v.Length;
+ // nbfilesmax++;
+
+ // }
+
+ // Loop that allows the backup of different files
+ // foreach (var v in queryList1Only)
+ // {
+ // string tempPath = Path.Combine(pathC, v.Name);
+ // Systems which allows to insert the values of each file in the report file.
+ // DataState.SourceFile = Path.Combine(pathA, v.Name);
+ // DataState.TargetFile = tempPath;
+ // DataState.TotalSize = nbfilesmax;
+ // DataState.TotalFile = TotalSize;
+ // DataState.TotalSizeRest = TotalSize - size;
+ // DataState.FileRest = nbfilesmax - nbfiles;
+ // DataState.Progress = progs;
+
+ // UpdateStatefile();//Call of the function to start the state file system
+
+ // if (PriorityExt(Path.GetExtension(v.Name)))
+ // {
+ // if (CryptExt(Path.GetExtension(v.Name)))
+ // {
+ // cryptwatch.Start();
+ // Encrypt(DataState.SourceFile, tempPath);
+ // cryptwatch.Stop();
+ // }
+ // else
+ // {
+ // v.CopyTo(tempPath, true); //Function that allows you to copy the file to its new folder.
+ // }
+ // }
+ // else
+ // {
+ // if (CryptExt(Path.GetExtension(v.Name)))
+ // {
+ // cryptwatch.Start();
+ // Encrypt(DataState.SourceFile, tempPath);
+ // cryptwatch.Stop();
+ // }
+ // else
+ // {
+ // v.CopyTo(tempPath, true); //Function that allows you to copy the file to its new folder.
+ // }
+ // }
+
+ // size += v.Length;
+ // nbfiles++;
+ // }
+
+ // System which allows the values to be reset to 0 at the end of the backup
+ // DataState.SourceFile = null;
+ // DataState.TargetFile = null;
+ // DataState.TotalFile = 0;
+ // DataState.TotalSize = 0;
+ // DataState.TotalSizeRest = 0;
+ // DataState.FileRest = 0;
+ // DataState.Progress = 0;
+ // DataState.SaveState = false;
+ // UpdateStatefile();//Call of the function to start the state file system
+
+ // stopwatch.Stop(); //Stop the stopwatch
+ // this.TimeTransfert = stopwatch.Elapsed; // Transfer of the chrono time to the variable
+ // this.CryptTransfert = cryptwatch.Elapsed;
+ //}
+
+
+
+
+
+
+ protected void OnBackupStarted(SaveModel save)
+ {
+ BackupStarted?.Invoke(this, new BackupEventArgs
{
- Console.WriteLine("Le répertoire source n'existe pas.");
- return;
- }
+ SourcePath = save.InPath,
+ TargetPath = save.OutPath,
+ StartTime = DateTime.Now
+ });
+ }
- // Crée le répertoire cible s'il n'existe pas encore
- if (!Directory.Exists(targetDirPath))
+ protected void OnBackupCompleted(SaveModel save)
+ {
+ BackupCompleted?.Invoke(this, new BackupEventArgs
{
- Directory.CreateDirectory(targetDirPath);
- }
+ SourcePath = save.InPath,
+ TargetPath = save.OutPath,
+ EndTime = DateTime.Now
+ });
+ }
+ }
- // Obtient la liste des fichiers et des sous-répertoires dans le répertoire source
- string[] files = Directory.GetFiles(sourceDirPath);
- string[] subdirectories = Directory.GetDirectories(sourceDirPath);
-
- // Copie les fichiers
- foreach (string filePath in files)
- {
- string fileName = Path.GetFileName(filePath);
- string targetFilePath = Path.Combine(targetDirPath, fileName);
- stateModel.SourceFilePath = filePath;
- stateModel.TargetFilePath = targetFilePath;
-
- stateManagerService.UpdateStateFile();
-
- DateTime start = DateTime.Now;
- File.Copy(filePath, targetFilePath, true); // Le paramètre true permet d'écraser le fichier s'il existe déjà dans le répertoire cible
- stateModel.NbFilesLeftToDo = stateModel.NbFilesLeftToDo > 0 ? stateModel.NbFilesLeftToDo - 1 : 0;
- start = DateTime.Now;
-
- loggerService!.loggerModel!.FileEncryptionTime = (DateTime.Now - start).ToString();
-
- stateManagerService.UpdateStateFile();
- loggerService!.loggerModel!.Name = stateModel.SaveName;
- loggerService!.loggerModel!.FileSource = filePath;
- loggerService!.loggerModel.FileTarget = targetFilePath;
- loggerService!.loggerModel.FileSize = new FileInfo(filePath).Length.ToString();
- loggerService!.loggerModel.FileTransferTime = (DateTime.Now - start).ToString();
- loggerService.AddEntryLog();
- }
+
+}
- // Copie les sous-répertoires récursivement
- foreach (string subdirectory in subdirectories)
- {
- string subdirectoryName = Path.GetFileName(subdirectory);
- string targetSubdirectoryPath = Path.Combine(targetDirPath, subdirectoryName);
- CopyDirectory(subdirectory, targetSubdirectoryPath, stateModel); // Appel récursif pour copier les sous-répertoires
- }
- }
- }
+public class BackupEventArgs : EventArgs
+{
+ public string SourcePath { get; set; }
+ public string TargetPath { get; set; }
+ public DateTime StartTime { get; set; }
+ public DateTime EndTime { get; set; }
}
+
+
diff --git a/App.Core/Services/LoggerService.cs b/App.Core/Services/LoggerService.cs
index de31b5c..09471c6 100644
--- a/App.Core/Services/LoggerService.cs
+++ b/App.Core/Services/LoggerService.cs
@@ -1,4 +1,5 @@
-using System.Text.Json;
+using System.Reflection.Metadata.Ecma335;
+using System.Text.Json;
using System.Xml.Serialization;
using App.Core.Models;
using static System.Runtime.InteropServices.JavaScript.JSType;
@@ -21,40 +22,6 @@ public LoggerService()
loggerModel = new();
}
-
- //public void WriteLog()
- //{
- // //TODO : Gerer les exeptions
-
- // try
- // {
- // // Serialize the log model to JSON
-
- // string logEntry = JsonSerializer.Serialize(loggerModel, options) + ",";
- // string jsonlogEntry = JsonSerializer.Serialize(loggerModel, options) + ",";
- // // Append the log entry to the log file or create if not exist
- // using StreamWriter LogWriter = File.AppendText(jsonlogFilePath);
- // LogWriter.WriteLineAsync(jsonlogEntry);
-
- // // Serialize the log model to XML
- // using StringWriter xmlStringWriter = new();
- // XmlSerializer xmlSerializer = new(typeof(loggerModel));
- // xmlSerializer.Serialize(xmlStringWriter, loggerModel);
- // string xmlLogEntry = xmlStringWriter.ToString();
- // // Append the XML log entry to the XML log file or create if not exist
-
- // using StreamWriter xmlLogWriter = File.AppendText(xmlLogFilePath);
- // xmlLogWriter.WriteLineAsync(xmlLogEntry);
- // }
- // catch (Exception ex)
- // {
- // Console.WriteLine($"Error writing to log file: {ex.Message}");
-
- // }
- //}
- ///
- /// Method to open the log file
- ///
public void OpenLogFile()
{
// Open the log file in notepad
@@ -73,14 +40,22 @@ public void CreateLogFile()
File.WriteAllText(jsonlogFilePath, "[]");
}
- public void AddEntryLog()
+ public string GetLogFormat()
+ {
+ if (configService.LogsFormat == "JSON") return jsonlogFilePath;
+ else return xmlLogFilePath;
+ }
+
+ public void AddEntryLog(StreamWriter streamWriter)
{
if (configService.LogsFormat == "JSON")
{
try
{
- using StreamWriter logWriter = File.AppendText(jsonlogFilePath);
- logWriter.WriteLineAsync(JsonSerializer.Serialize(loggerModel, options) + ",");
+ using (streamWriter = File.AppendText(jsonlogFilePath)) ;
+ {
+ streamWriter.WriteLineAsync(JsonSerializer.Serialize(loggerModel, options) + ",");
+ }
}
catch (InvalidOperationException)
{
@@ -93,7 +68,7 @@ public void AddEntryLog()
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(LoggerModel));
- using (StreamWriter streamWriter = File.AppendText(xmlLogFilePath))
+ using (streamWriter = File.AppendText(xmlLogFilePath))
{
xmlSerializer.Serialize(streamWriter, loggerModel );
}
diff --git a/App.Core/Services/SaveService.cs b/App.Core/Services/SaveService.cs
index 960cb24..29cf401 100644
--- a/App.Core/Services/SaveService.cs
+++ b/App.Core/Services/SaveService.cs
@@ -5,55 +5,260 @@
namespace App.Core.Services
{
- public class SaveService
+ public class SaveService : IDisposable
{
- public required ObservableCollection ListStateManager { get; set; } = [];
- public required ObservableCollection ListSaveModel { get; set; } = [];
- private readonly ConfigService configService = new();
+ public ObservableCollection ListStateManager { get; set; } = [];
+ public ObservableCollection ListSaveModel { get; set; } = [];
+ public ManualResetEvent pauseEvent { get; private set; } = new ManualResetEvent(false);
+ public ManualResetEvent resumeEvent { get; private set; } = new ManualResetEvent(true);
+ public ManualResetEvent stopEvent { get; private set; } = new ManualResetEvent(false);
+
+ private int progress = 0;
+ //TODO : Mettre manualResetsEvent et autre event resume
+
+ private readonly StreamWriter? logWriter ;
+ private readonly StreamWriter? stateWriter;
+
+ private readonly StateManagerService stateManagerService = new();
public CopyService copyService = new();
private readonly JsonSerializerOptions options = new()
{
WriteIndented = true
};
+ private Thread saveThread;
+ private long fileDo =0;
+ private long fileTotal = 0;
+
public SaveService()
{
+ //logWriter = new StreamWriter(loggerService.GetLogFormat());
+ //stateWriter = new StreamWriter(StateManagerService.stateFilePath);
LoadSave();
copyService.stateManagerService.listStateModel = ListStateManager;
- copyService.stateManagerService.UpdateStateFile();
+ //copyService.stateManagerService.UpdateStateFile(stateWriter);
}
public bool IsSoftwareRunning()
{
// Check if the software is running (e.g., "notepad.exe")
- Process[] processes = Process.GetProcessesByName(configService.Software);
- if (processes.Length > 0)
+
+ Process[] processes = Process.GetProcessesByName("mspaint");
+ return processes.Length > 0;
+
+
+ }
+
+ public void ExecuteSave(List saveModel, ThreadManagerService threadManagerService)
+ {
+ foreach (SaveModel save in saveModel)
{
- return true;
+ copyService = new();
+ copyService.CopyModel.SourcePath = save.InPath;
+ copyService.CopyModel.TargetPath = save.OutPath;
+ copyService.stateManagerService.listStateModel = ListStateManager;
+
+ // Start copying process in a separate thread
+
+
+ copyService.BackupStarted += (sender, args) =>Console.WriteLine($"Backup started from {args.SourcePath} to {args.TargetPath} at {args.StartTime}");
+
+ copyService.BackupCompleted += (sender, args) => Console.WriteLine($"Backup completed from {args.SourcePath} to {args.TargetPath} at {args.EndTime}");
+
+
+ Thread thread = new Thread(() => copyService.ExecuteCopy(save, logWriter!, stateWriter!));
+ threadManagerService.AddThread(thread);
+ thread.Start();
+
+ copyService.BackupStarted -= (sender, args) => Console.WriteLine($"Backup started from {args.SourcePath} to {args.TargetPath} at {args.StartTime}");
+
+ copyService.BackupCompleted -= (sender, args) =>Console.WriteLine($"Backup completed from {args.SourcePath} to {args.TargetPath} at {args.EndTime}");
+
+
}
- else
+ }
+
+ public void LaunchSave(SaveModel saveModel)
+ {
+ //TODO : Detection logicel Métier
+
+ if (saveModel.Type == "Complete")
{
- return false;
+ // Set the resume event to allow it to be resumed later
+ saveThread = new Thread(() =>
+ {
+ //resumeEvent.Set();
+ //pauseEvent.Set();
+
+ stopEvent.Reset();
+ fileDo = 0;
+ CompleteSave(saveModel.InPath, saveModel.OutPath, true, saveModel);
+ fileDo = fileTotal;
+ saveModel.percentage = (fileDo * 100 / fileTotal);
+ });
+
+ // Start the thread
+ saveThread.Start();
+
}
+ if (saveModel.Type == "Incremental")
+ {
+ //IncrementalSave(saveModel.InPath, saveModel.OutPath, true);
+ }
}
- public void ExecuteSave(SaveModel saveModel)
+ public void PauseSave()
{
- // Method to execute the copy service
- // Execute the copy service
- copyService.CopyModel.SourcePath = saveModel.InPath;
- copyService.CopyModel.TargetPath = saveModel.OutPath;
- copyService.stateManagerService.listStateModel = ListStateManager;
- copyService.ExecuteCopy(saveModel);
+ pauseEvent.Set(); // Reset the pause event to block threads
+ resumeEvent.Reset(); // Set the resume event to allow it to be resumed later
+ }
+
+ public void StopSave()
+ {
+ fileDo = 0;
+ stopEvent.Set(); // Signal the stop event to stop the save operation
+ }
+ public void ResumeSave()
+ {
+ pauseEvent.Reset(); // Signal the pause event to resume the save operation
+ resumeEvent.Set(); // Reset the resume event to block it until it's signaled again
}
- public void LoadSave()
+ private bool CompleteSave(string InPath, string OutPath, bool verif, SaveModel saveModel)
+ {
+ // DataState = new DataState(NameStateFile);
+ // this.DataState.SaveState = true;
+
+ // Wait for pauseEvent to be signaled before proceeding
+ pauseEvent.WaitOne(0);
+
+ while (IsSoftwareRunning() && !stopEvent.WaitOne(0))
+ {
+ // Software is running, wait for it to close
+ Thread.Sleep(1000);
+ // Display message box to inform the user that the software is still running
+ }
+
+ if (stopEvent.WaitOne(0))
+ {
+ // Stop event has been signaled, return false to indicate incomplete save
+ return false;
+ }
+
+ // Implement the logic with the event resume, pause, and stop
+
+ // Wait for resumeEvent to be signaled before continuing
+ resumeEvent.WaitOne();
+
+ fileTotal += Directory.GetFiles(InPath).Length;
+
+ // Recursively count files in subdirectories
+
+ fileTotal += CountFiles(InPath);
+
+ StateManagerModel stateModel = new()
+ {
+ SaveName = saveModel.SaveName,
+ State = "END"
+ };
+
+ foreach (StateManagerModel item in ListStateManager)
+ {
+ if (item.SaveName == stateModel.SaveName)
+ {
+ stateModel = item;
+ }
+ }
+
+ long TotalSize = 0;
+ long nbfilesmax = 0;
+ long size = 0;
+ long nbfiles = 0;
+
+ Stopwatch stopwatch = new Stopwatch();
+ stopwatch.Start(); // Starting the timed for the log file
+
+ DirectoryInfo dir = new DirectoryInfo(InPath); // Get the subdirectories for the specified directory.
+
+ if (!dir.Exists) // Check if the file is present
+ {
+ throw new DirectoryNotFoundException("ERROR 404 : Directory Not Found ! " + InPath);
+ }
+
+ DirectoryInfo[] dirs = dir.GetDirectories();
+ Directory.CreateDirectory(OutPath); // If the destination directory doesn't exist, create it.
+
+ FileInfo[] files = dir.GetFiles(); // Get the files in the directory and copy them to the new location.
+ if (verif) // Check for the status file if it needs to reset the variables
+ {
+ TotalSize = 0;
+ nbfilesmax = 0;
+ size = 0;
+ nbfiles = 0;
+
+ foreach (FileInfo file in files) // Loop to allow calculation of files and folder size
+ {
+ TotalSize += file.Length;
+ nbfilesmax++;
+ }
+ foreach (DirectoryInfo subdir in dirs) // Loop to allow calculation of subfiles and subfolder size
+ {
+ FileInfo[] Maxfiles = subdir.GetFiles();
+ foreach (FileInfo file in Maxfiles)
+ {
+ TotalSize += file.Length;
+ nbfilesmax++;
+ }
+ }
+
+ }
+
+ // Loop that allows to copy the files to make the backup
+ foreach (FileInfo file in files)
+ {
+ string tempPath = Path.Combine(OutPath, file.Name);
+
+ stateModel.SourceFilePath = Path.Combine(OutPath, file.Name);
+ stateModel.TargetFilePath = tempPath;
+ stateModel.TotalFilesToCopy = nbfilesmax;
+ stateModel.TotalFilesSize = TotalSize;
+ stateModel.NbFilesLeftToDo = nbfilesmax - nbfiles;
+ stateModel.State = "IN PROGRESS";
+
+ stateManagerService.UpdateStateFile(ListStateManager);
+
+ // Systems which allows to insert the values of each file in the report file.
+
+ file.CopyTo(tempPath, true); // Function that allows you to copy the file to its new folder.
+ nbfiles++;
+ fileDo+= nbfiles;
+ size += file.Length;
+ saveModel.percentage = (int)((fileDo * 100) / fileTotal);
+
+ // Calculate the global percentage of execution and store it in saveModel.percentage
+
+ }
+
+ // If copying subdirectories, copy them and their contents to new location.
+
+ foreach (DirectoryInfo subdir in dirs)
+ {
+ string tempPath = Path.Combine(OutPath, subdir.Name);
+ CompleteSave(subdir.FullName, tempPath, true, saveModel);
+ }
+
+ stopwatch.Stop(); // Stop the stopwatch
+ return false;
+ }
+
+
+ public ObservableCollection LoadSave()
{
if (File.Exists("saves.json"))
@@ -78,27 +283,21 @@ public void LoadSave()
File.WriteAllText("saves.json", "[]");
}
+ return ListSaveModel;
+
}
- ///
- /// Show info of a save
- ///
- ///
- ///
public Tuple ShowInfo(SaveModel saveModel)
{
return Tuple.Create(saveModel.SaveName, saveModel.InPath, saveModel.OutPath, saveModel.Type, saveModel.Date);
}
-
-
-
- public bool CreateSave(string inPath, string outPath, string type, string saveName)
+ public bool CreateSave(SaveModel saveModel)
{
try
{
- ListSaveModel.Add(new SaveModel { InPath = inPath, OutPath = outPath, Type = type, SaveName = saveName});
- ListStateManager.Add(new StateManagerModel { SaveName = saveName, SourceFilePath = inPath, TargetFilePath = outPath });
+ ListSaveModel.Add(saveModel);
+ ListStateManager.Add(new StateManagerModel { SaveName = saveModel.SaveName, SourceFilePath = saveModel.InPath, TargetFilePath = saveModel.OutPath });
File.WriteAllText("saves.json", JsonSerializer.Serialize(ListSaveModel, options));
return true;
}
@@ -107,16 +306,35 @@ public bool CreateSave(string inPath, string outPath, string type, string saveNa
return false;
}
}
-
-
+
public void DeleteSave(SaveModel saveModel)
{
ListSaveModel.Remove(saveModel);
}
-
+ public void Dispose()
+ {
+ logWriter?.Dispose();
+ stateWriter?.Dispose();
+ }
+
+ public int CountFiles(string directoryPath)
+ {
+ int fileCount = 0;
+
+ // Count files in the current directory
+ fileCount += Directory.GetFiles(directoryPath).Length;
+
+ // Recursively count files in subdirectories
+ foreach (string subDirectory in Directory.GetDirectories(directoryPath))
+ {
+ fileCount += CountFiles(subDirectory);
+ }
+
+ return fileCount;
+ }
}
}
diff --git a/App.Core/Services/StateManagerService.cs b/App.Core/Services/StateManagerService.cs
index 8a89083..4689d80 100644
--- a/App.Core/Services/StateManagerService.cs
+++ b/App.Core/Services/StateManagerService.cs
@@ -1,4 +1,5 @@
using App.Core.Models;
+using Newtonsoft.Json;
using System.Collections.ObjectModel;
using System.Text.Json;
@@ -6,16 +7,11 @@ namespace App.Core.Services
{
public class StateManagerService
{
-
+
public ObservableCollection? listStateModel;
- private readonly string stateFilePath = "state.json";
-
+ public static readonly string stateFilePath = "state.json";
- //Options for the JsonSerializer
- private readonly JsonSerializerOptions options = new()
- {
- WriteIndented = true
- };
+ private static Mutex mut = new();
public StateManagerService()
@@ -23,7 +19,7 @@ public StateManagerService()
//Create the state file if it does not exist
if (!File.Exists(stateFilePath))
{
- CreateStateFile();
+ //CreateStateFile();
}
//UpdateStateFile();
@@ -35,34 +31,42 @@ public void OpenStateFile()
System.Diagnostics.Process.Start("notepad.exe", stateFilePath);
}
- public void UpdateStateFile()
+
+ public void UpdateStateFile(ObservableCollection stateManagerModels)
{
- // Clear the state file
- ClearStateFile();
- int i = 0;
- foreach (StateManagerModel stateModel in listStateModel!)
+ //TODO : Voir les states files
+ mut.WaitOne();
+ try
{
- using (StreamWriter stateWriter = File.AppendText(stateFilePath))
+ ClearStateFile();
+ // Open the file for writing (append mode)
+ StreamWriter? streamWriter = null;
+ using (streamWriter = File.AppendText(stateFilePath))
{
- stateWriter.WriteLineAsync(JsonSerializer.Serialize(stateModel, options) + ",");
+ foreach (StateManagerModel stateModel in stateManagerModels!)
+ {
+ // Write the serialized stateModel to the file
+ streamWriter.WriteLineAsync(JsonConvert.SerializeObject(stateModel, Formatting.Indented) + Environment.NewLine);
+ }
}
- //Increment the index to get the next save name
- i += 1;
+ streamWriter?.Dispose();
}
+ catch (IOException ex)
+ {
+ // Handle the exception (e.g., log or retry)
+ Console.WriteLine($"Error updating state file: {ex.Message}");
+ }
+ mut.ReleaseMutex();
}
- public void CreateStateFile()
- {
- // Create the state file
- File.WriteAllText(stateFilePath, "[]");
- }
public void ClearStateFile()
{
// Clear the state file
- File.WriteAllText(stateFilePath, "");
+ File.WriteAllText(stateFilePath, "") ;
}
+
}
}
diff --git a/App.Core/Services/ThreadManagerService.cs b/App.Core/Services/ThreadManagerService.cs
new file mode 100644
index 0000000..1af7141
--- /dev/null
+++ b/App.Core/Services/ThreadManagerService.cs
@@ -0,0 +1,41 @@
+using System.Collections.Generic;
+using System.Threading;
+
+namespace App.Core.Services
+{
+ public class ThreadManagerService
+ {
+ private List runningThreads = new List();
+
+ public void AddThread(Thread thread)
+ {
+
+ runningThreads.Add(thread);
+
+ }
+
+ public void RemoveThread(Thread thread)
+ {
+ runningThreads.Remove(thread);
+ }
+
+ public bool AreThreadsRunning(int threadNumber)
+ {
+ if (runningThreads.Count == 0 || threadNumber >= runningThreads.Count)
+ {
+ return false;
+ }
+
+ try
+ {
+ Console.WriteLine($"Thread {runningThreads[threadNumber].ThreadState}");
+ return runningThreads[threadNumber].ThreadState == ThreadState.Running;
+ }
+ catch (System.Exception)
+ {
+ return false;
+ }
+ }
+
+ }
+}
diff --git a/WpfApp/MainWindow.xaml b/WpfApp/MainWindow.xaml
index 8011f17..fda4c68 100644
--- a/WpfApp/MainWindow.xaml
+++ b/WpfApp/MainWindow.xaml
@@ -3,34 +3,105 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:local="clr-namespace:WpfApp.Views"
+ xmlns:local="clr-namespace:WpfApp.ViewModels"
mc:Ignorable="d"
Title="EasySave" Height="475" Width="800" MinHeight="475" MinWidth="800">
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WpfApp/MainWindow.xaml.cs b/WpfApp/MainWindow.xaml.cs
index 0d685fc..2eef2de 100644
--- a/WpfApp/MainWindow.xaml.cs
+++ b/WpfApp/MainWindow.xaml.cs
@@ -1,13 +1,10 @@
-using System.Text;
+using App.Core.Models;
+using Microsoft.Win32;
+using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
+using WpfApp.ViewModels;
namespace WpfApp
{
@@ -16,9 +13,138 @@ namespace WpfApp
///
public partial class MainWindow : Window
{
+ private readonly MainViewModel? viewModel;
+ public ObservableCollection Saves { get; set; } = new ObservableCollection();
+
public MainWindow()
{
InitializeComponent();
+ viewModel = new MainViewModel();
+ List_Save.Items.Clear();
+ LoadSave();
+ List_Save.ItemsSource = this.Saves;
+ }
+
+ private void LoadSave()
+ {
+ this.Saves = viewModel!.saves;
+ }
+
+ private void addSave_Click(object sender, RoutedEventArgs e)
+ {
+ SaveModel save = new SaveModel
+ {
+ SaveName = SaveName.Text,
+ InPath = SourceName.Text,
+ OutPath = DestinationName.Text,
+ Type = IsComplete.IsChecked != null && (bool)IsComplete.IsChecked ? "Complete" : "Incremental",
+ EncryptChoice = IsEncrypted.IsChecked != null && (bool)IsEncrypted.IsChecked ? "True" : "False"
+ };
+ try
+ {
+ if (string.IsNullOrEmpty(SaveName.Text) || SourceName.Text == "" || DestinationName.Text == "" || Destination.Text == "Destination" || Source.Text == "Source" )
+ {
+ MessageBox.Show("Please fill in all the fields");
+ return;
+ }
+
+ viewModel!.AddSave(save);
+ MessageBox.Show("Save added successfully");
+ }
+ catch
+ {
+ // TODO : Handle exception
+ }
+ }
+
+ private void SourcePopup_Click(object sender, RoutedEventArgs e)
+ {
+ OpenFolderDialog dialog = new OpenFolderDialog(); //Declaration of the method to open the window to choose the folder path.
+ dialog.DefaultDirectory = "";
+ if ((bool)dialog.ShowDialog())
+ {
+ SourceName.Text = dialog.FolderName;
+ }
+
+
+ }
+
+ private void DestinationPopup_Click(object sender, RoutedEventArgs e)
+ {
+ OpenFolderDialog dialog = new OpenFolderDialog(); //Declaration of the method to open the window to choose the folder path.
+ dialog.DefaultDirectory = "";
+ if ((bool)dialog.ShowDialog())
+ {
+ DestinationName.Text = dialog.FolderName;
+ }
+ }
+
+ private void StartSave_Click(object sender, RoutedEventArgs e)
+ {
+ if (List_Save.SelectedItem != null)
+ {
+ // Start the save operation asynchronously
+ var selectedItem = (SaveModel)List_Save.SelectedItem;
+ var row_init = (DataGridRow)List_Save.ItemContainerGenerator.ContainerFromItem(selectedItem);
+ if (row_init != null)
+ {
+ row_init.Background = Brushes.Green;
+ }
+ viewModel!.LaunchSave(selectedItem);
+
+ }
+ else
+ {
+ // Handle case where no item is selected
+ }
+ }
+
+
+
+
+
+
+ private void DeleteSave_Click(object sender, RoutedEventArgs e)
+ {
+ if (List_Save.SelectedItem != null)
+ {
+ // Start the save operation
+ viewModel!.DeleteSave((SaveModel)List_Save.SelectedItem);
+ }
+ }
+
+ private void PlaySave_Click(object sender, RoutedEventArgs e)
+ {
+ var selectedItem = (SaveModel)List_Save.SelectedItem;
+ var row_init = (DataGridRow)List_Save.ItemContainerGenerator.ContainerFromItem(selectedItem);
+ if (row_init != null)
+ {
+ row_init.Background = Brushes.Green;
+ }
+ viewModel!.PlaySave();
+ }
+
+ private void PauseSave_Click(object sender, RoutedEventArgs e)
+ {
+ var selectedItem = (SaveModel)List_Save.SelectedItem;
+ var row_init = (DataGridRow)List_Save.ItemContainerGenerator.ContainerFromItem(selectedItem);
+ if (row_init != null)
+ {
+ row_init.Background = Brushes.Orange;
+ }
+ viewModel!.PauseSave();
+ }
+
+
+ private void StopSave_Click(object sender, RoutedEventArgs e)
+ {
+ var selectedItem = (SaveModel)List_Save.SelectedItem;
+ var row_init = (DataGridRow)List_Save.ItemContainerGenerator.ContainerFromItem(selectedItem);
+ if (row_init != null)
+ {
+ row_init.Background = Brushes.Red;
+ }
+ viewModel!.StopSave();
}
}
}
\ No newline at end of file
diff --git a/WpfApp/ViewModels/ListViewModel.cs b/WpfApp/ViewModels/ListViewModel.cs
index 00d49fa..8791323 100644
--- a/WpfApp/ViewModels/ListViewModel.cs
+++ b/WpfApp/ViewModels/ListViewModel.cs
@@ -6,113 +6,111 @@
namespace WpfApp.ViewModels
{
- class ListViewModel : INotifyPropertyChanged
+ class ListViewModel
{
- private SaveModel _selected;
- public SaveModel Selected
+ public ObservableCollection Selected
{
- get => _selected;
+ get => Selected;
set
{
- if (_selected != value)
+ if (Selected != value)
{
- _selected = value;
- OnPropertyChanged();
+ Selected = value;
}
}
}
- public ObservableCollection listStateManager { get; set; } = new ObservableCollection();
- public ObservableCollection listSaveModel{ get; set; } = new ObservableCollection();
- public ObservableCollection Items { get; set; } = new ObservableCollection();
-
-
- private SaveService? saveService;
-
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- public RelayCommand RefreshCommand { get; }
- public RelayCommand CreateCommand { get; }
- public RelayCommand ExecuteCommand { get; }
- public RelayCommand DeleteCommand { get; }
-
- public ListViewModel()
- {
- saveService = new()
- {
- ListStateManager = this.listStateManager,
- ListSaveModel = this.listSaveModel
- };
-
- saveService.LoadSave();
- this.listSaveModel = saveService.ListSaveModel;
- this.listStateManager = saveService.ListStateManager;
- foreach (var item in listSaveModel)
- {
- Items.Add(item);
- }
- RefreshCommand = new RelayCommand(Refresh);
- CreateCommand = new RelayCommand(Create);
- ExecuteCommand = new RelayCommand(Execute);
- DeleteCommand = new RelayCommand(Delete);
-
- }
-
- public void Execute()
- {
- if (Selected != null)
- {
- Task.Run(() => saveService!.ExecuteSave(Selected));
- }
- else
- {
- // Handle case where no item is selected
- }
- }
-
- public void Create()
- {
- // Create a new instance of SaveModel (assuming SaveModel has a default constructor)
- var newSaveModel = new SaveModel();
-
- // Add the new SaveModel instance to the Items collection
- Items.Add(newSaveModel);
-
- // Optionally, select the newly added item
- newSaveModel = Selected;
-
- saveService!.CreateSave(newSaveModel.InPath, newSaveModel.OutPath, newSaveModel.Type, newSaveModel.SaveName);
- Thread.Sleep(500);
- Refresh();
- }
-
- public void Refresh()
- {
- Items.Clear();
- foreach (var item in listSaveModel)
- {
- Items.Add(item);
- }
- }
-
- public void Delete()
- {
- if (Selected != null)
- {
- saveService!.DeleteSave(Selected);
- Refresh();
- }
- else
- {
- // Handle case where no item is selected
- }
- }
-
- protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
+ //public ObservableCollection listStateManager { get; set; } = new ObservableCollection();
+ //public ObservableCollection listSaveModel{ get; set; } = new ObservableCollection();
+ //public ObservableCollection Items { get; set; } = new ObservableCollection();
+
+
+ //private SaveService? saveService;
+
+
+ //public event PropertyChangedEventHandler PropertyChanged;
+
+ //public RelayCommand RefreshCommand { get; }
+ //public RelayCommand CreateCommand { get; }
+ //public RelayCommand ExecuteCommand { get; }
+ //public RelayCommand DeleteCommand { get; }
+
+ //public ListViewModel()
+ //{
+ // saveService = new()
+ // {
+ // ListStateManager = this.listStateManager,
+ // ListSaveModel = this.listSaveModel
+ // };
+
+ // saveService.LoadSave();
+ // this.listSaveModel = saveService.ListSaveModel;
+ // this.listStateManager = saveService.ListStateManager;
+ // foreach (var item in listSaveModel)
+ // {
+ // Items.Add(item);
+ // }
+ // RefreshCommand = new RelayCommand(Refresh);
+ // CreateCommand = new RelayCommand(Create);
+ // ExecuteCommand = new RelayCommand(Execute);
+ // DeleteCommand = new RelayCommand(Delete);
+
+ //}
+
+ //public void Execute()
+ //{
+ // if (Selected != null)
+ // {
+ // Task.Run(() => saveService!.ExecuteSave(Selected));
+ // }
+ // else
+ // {
+ // // Handle case where no item is selected
+ // }
+ //}
+
+ //public void Create()
+ //{
+ // // Create a new instance of SaveModel (assuming SaveModel has a default constructor)
+ // var newSaveModel = new ObservableCollection();
+
+ // // Add the new SaveModel instance to the Items collection
+ // Items.Add(newSaveModel);
+
+ // // Optionally, select the newly added item
+ // newSaveModel = Selected;
+
+ // saveService!.CreateSave(newSaveModel.InPath, newSaveModel.OutPath, newSaveModel.Type, newSaveModel.SaveName);
+ // Thread.Sleep(500);
+ // Refresh();
+ //}
+
+ //public void Refresh()
+ //{
+ // Items.Clear();
+ // foreach (var item in listSaveModel)
+ // {
+ // Items.Add(item);
+ // }
+ //}
+
+ //public void Delete()
+ //{
+ // if (Selected != null)
+ // {
+ // saveService!.DeleteSave(Selected);
+ // Refresh();
+ // }
+ // else
+ // {
+ // // Handle case where no item is selected
+ // }
+ //}
+
+ //protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ //{
+ // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ //}
}
}
diff --git a/WpfApp/ViewModels/MainViewModel.cs b/WpfApp/ViewModels/MainViewModel.cs
new file mode 100644
index 0000000..ecc20b9
--- /dev/null
+++ b/WpfApp/ViewModels/MainViewModel.cs
@@ -0,0 +1,68 @@
+using App.Core.Models;
+using App.Core.Services;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows.Media.Animation;
+
+namespace WpfApp.ViewModels
+{
+ public class MainViewModel
+ {
+ public readonly ObservableCollection saves = new();
+ private readonly SaveService saveService = new();
+ private readonly HashSet runningSaves = new(); // HashSet to store the IDs of running saves
+ public int percentage { get; set; } = 100;
+
+
+
+ public MainViewModel()
+ {
+ saves = saveService.LoadSave();
+ }
+
+ public void AddSave(SaveModel save)
+ {
+ saveService.CreateSave(save);
+ }
+
+
+
+ public void DeleteSave(SaveModel saveModel)
+ {
+ saveService.DeleteSave(saveModel);
+ }
+
+ public void PlaySave()
+ {
+ saveService.ResumeSave();
+ }
+
+ public void PauseSave()
+ {
+ saveService.PauseSave();
+ }
+
+ public void StopSave()
+ {
+ saveService.StopSave();
+ }
+
+ public bool IsSaveRunning(SaveModel saveModel)
+ {
+ lock (runningSaves)
+ {
+ return runningSaves.Contains(saveModel); // Check if the saveModel instance is in the runningSaves collection
+ }
+ }
+
+ public void LaunchSave(SaveModel saveModel)
+ {
+ // Vérifiez si la sauvegarde est en cours d'exécution
+ saveService.LaunchSave(saveModel);
+
+ }
+
+
+
+ }
+}
diff --git a/WpfApp/Views/ControlView.xaml b/WpfApp/Views/ControlView.xaml
deleted file mode 100644
index 5726ac5..0000000
--- a/WpfApp/Views/ControlView.xaml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/WpfApp/Views/ControlView.xaml.cs b/WpfApp/Views/ControlView.xaml.cs
deleted file mode 100644
index 6e8551a..0000000
--- a/WpfApp/Views/ControlView.xaml.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
-
-namespace WpfApp.Views
-{
- ///
- /// Logique d'interaction pour ControlView.xaml
- ///
- public partial class ControlView : UserControl
- {
- public ControlView()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/WpfApp/Views/ListView.xaml b/WpfApp/Views/ListView.xaml
deleted file mode 100644
index 26fc407..0000000
--- a/WpfApp/Views/ListView.xaml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WpfApp/Views/ListView.xaml.cs b/WpfApp/Views/ListView.xaml.cs
deleted file mode 100644
index 63d2c15..0000000
--- a/WpfApp/Views/ListView.xaml.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
-
-namespace WpfApp.Views
-{
- ///
- /// Logique d'interaction pour ListView.xaml
- ///
- public partial class ListView : UserControl
- {
- public ListView()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/WpfApp/Views/MenuView.xaml b/WpfApp/Views/MenuView.xaml
deleted file mode 100644
index 22a783a..0000000
--- a/WpfApp/Views/MenuView.xaml
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- EasySave
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WpfApp/Views/MenuView.xaml.cs b/WpfApp/Views/MenuView.xaml.cs
deleted file mode 100644
index cce221c..0000000
--- a/WpfApp/Views/MenuView.xaml.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
-
-namespace WpfApp.Views
-{
- ///
- /// Logique d'interaction pour Menu.xaml
- ///
- public partial class Menu : UserControl
- {
- public Menu()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/WpfApp/WpfApp.csproj b/WpfApp/WpfApp.csproj
index c6fdd78..7f2af4d 100644
--- a/WpfApp/WpfApp.csproj
+++ b/WpfApp/WpfApp.csproj
@@ -67,4 +67,8 @@
+
+
+
+
diff --git a/WpfApp/WpfApp.csproj.user b/WpfApp/WpfApp.csproj.user
index e4c3053..644b0a6 100644
--- a/WpfApp/WpfApp.csproj.user
+++ b/WpfApp/WpfApp.csproj.user
@@ -6,29 +6,9 @@
Designer
-
-
- Code
-
-
- Code
-
-
- Code
-
-
Designer
-
- Designer
-
-
- Designer
-
-
- Designer
-
\ No newline at end of file