Add project files.

This commit is contained in:
Radio
2021-10-28 14:02:13 +02:00
parent 7a9bc68a84
commit eff2281913
22 changed files with 1080 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31702.278
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPFLinkTool", "WPFLinkTool\WPFLinkTool.csproj", "{F7A5BA83-57A5-40C8-87AB-14DC84AE7529}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F7A5BA83-57A5-40C8-87AB-14DC84AE7529}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7A5BA83-57A5-40C8-87AB-14DC84AE7529}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7A5BA83-57A5-40C8-87AB-14DC84AE7529}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7A5BA83-57A5-40C8-87AB-14DC84AE7529}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C28B0299-C112-4902-83AA-89612681ECEC}
EndGlobalSection
EndGlobal
+36
View File
@@ -0,0 +1,36 @@
<Window x:Class="WPFLinkTool.AddInstanceDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:WPFLinkTool"
mc:Ignorable="d"
Title="AddInstanceDialog" Height="250" Width="500"
WindowStartupLocation="CenterOwner">
<Border Margin="10">
<StackPanel>
<TextBlock IsEnabled="{Binding ElementName=CreateButton, Path=IsEnabled}" Text="Instance name"></TextBlock>
<TextBox Text="{Binding InstanceName}"></TextBox>
<TextBlock IsEnabled="{Binding ElementName=CreateButton, Path=IsEnabled}" Text="Data source path"></TextBlock>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Text="{Binding DataSource , Mode=TwoWay}"></TextBox>
<Button IsEnabled="{Binding ElementName=CreateButton, Path=IsEnabled}" Command="{Binding OpenBrowseDialog}" Grid.Column="1" Content="Browse..."></Button>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<RadioButton IsEnabled="{Binding ElementName=CreateButton, Path=IsEnabled}" Content="Move files" Grid.Column="0"></RadioButton>
<RadioButton IsEnabled="{Binding ElementName=CreateButton, Path=IsEnabled}" Content="Copy files" Grid.Column="1" IsChecked="{Binding IsCopyChecked}"></RadioButton>
</Grid>
<Button x:Name="CreateButton" Command="{Binding AddInstanceCommand}">Create instance</Button>
<TextBlock Text="{Binding StatusText}"></TextBlock>
<ProgressBar Height="30" Value="{Binding Progress}"></ProgressBar>
</StackPanel>
</Border>
</Window>
+28
View File
@@ -0,0 +1,28 @@
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.Shapes;
namespace WPFLinkTool
{
/// <summary>
/// Interaction logic for AddInstanceDialog.xaml
/// </summary>
public partial class AddInstanceDialog : Window
{
public AddInstanceDialog(SharedViewModel shared)
{
InitializeComponent();
DataContext = new AddInstanceViewModel(shared);
}
}
}
+9
View File
@@ -0,0 +1,9 @@
<Application x:Class="WPFLinkTool.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFLinkTool"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
+17
View File
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace WPFLinkTool
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
+10
View File
@@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
+65
View File
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using static WPFLinkTool.Global;
namespace WPFLinkTool
{
public class DBInfo
{
public List<DataInstance> InstanceList { get; set; }
public int InstanceCount => InstanceList.Count;
public long DBSize
{
get
{
long size = 0;
DirectoryInfo dir = new(dbDir);
foreach (var file in dir.GetFiles())
{
size += file.Length;
}
return size;
}
}
public long IndividualSize
{
get
{
long size = 0;
foreach (DataInstance instance in InstanceList)
{
size += instance.Size;
}
return size;
}
}
public DBInfo()
{
if (InstanceList == null)
InstanceList = new();
}
public void SaveToXml()
{
XmlSerializer serializer = new(typeof(DBInfo));
TextWriter writer = new StreamWriter(DBInfoPath);
serializer.Serialize(writer, this);
}
public void UpdateDBSize()
{
}
}
}
+32
View File
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static WPFLinkTool.Global;
namespace WPFLinkTool
{
public class DataInstance
{
public string InstanceName { get; set; }
public List<InstanceFileInfo> InstanceFiles { get; set; }
public int Entries { get; set; }
public long Size { get; set; }
public string PrettySize => ReadableSize(Size);
public DataInstance(string name, List<InstanceFileInfo> fileInfos, int entries, long size)
{
InstanceName = name;
InstanceFiles = fileInfos;
Entries = entries;
Size = size;
}
public DataInstance()
{
}
}
}
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static WPFLinkTool.Global;
namespace WPFLinkTool
{
public class InstanceFileInfo
{
public string OriginalFileName { get; set; }
public string HashedFileName { get; set; }
public string Location { get; set; }
public long SizeBytes { get; set; }
public string PrettySize => ReadableSize(SizeBytes);
public InstanceFileInfo(string orgFName, string hashFName, string loc, long size)
{
OriginalFileName = orgFName;
HashedFileName = hashFName;
Location = loc;
SizeBytes = size;
}
public InstanceFileInfo()
{
}
}
}
+42
View File
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFLinkTool
{
public class Global
{
//public static string curDir = @"F:\Torrents\bemaniso.ws\HardLinkUI";
//public static string curDir = @"C:\Tools and stuff\WPFLinkTool";
public static string curDir = Directory.GetCurrentDirectory();
public static string dbDir = curDir + @"\DB";
public static string xmlDir = curDir + @"\XML";
public static string DBInfoPath = curDir + @"\DBInfo.xml";
public static string ReadableSize(long size)
{
if (size < 1024f)
{
return $"{size} B";
}
if (size > 1024f && size < 1048576f)
{
return $"{Math.Round(size / 1024f, 2)} KB";
}
if (size > 1048576f && size < 1073741824f)
{
return $"{Math.Round(size / 1048576f, 2)} MB";
}
if (size > 1073741824f)
{
return $"{Math.Round(size / 1073741824f, 2)} GB";
}
else return "what?";
}
}
}
+64
View File
@@ -0,0 +1,64 @@
<Window x:Class="WPFLinkTool.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:WPFLinkTool"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="500">
<Border Padding="10">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding DBSize, StringFormat=DB size: {0}}"></TextBlock>
<TextBlock Grid.Column="1" Text="{Binding SumSize, StringFormat=Instance size sum: {0}}"></TextBlock>
</Grid>
<Grid Margin="0 2 0 2">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Command="{Binding OpenAddInstanceWindow}" Grid.Column="0">Add instance</Button>
<Button IsEnabled="{Binding LinkButtonEnabled}" Command="{Binding MakeHardLinksCommand}" Grid.Column="1">Make hard links</Button>
<Button IsEnabled="{Binding UIEnabled}" Command="{Binding DeleteUnusedCommand}" Grid.Column="2">Delete unused files</Button>
<Button IsEnabled="{Binding LinkButtonEnabled}" Command="{Binding DeleteInstanceCommand}" Grid.Column="3">Delete instance</Button>
</Grid>
<DockPanel MaxHeight="300" Margin="0 2 0 2">
<ScrollViewer VerticalScrollBarVisibility="Visible">
<ItemsControl ItemsSource="{Binding InstanceList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<RadioButton x:Name="RdioBtn" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Path=DataContext.SelectedInstanceCommand}" CommandParameter="{Binding ElementName=InstName, Path=Text}" Grid.Column="0" GroupName="InstanceGroup"></RadioButton>
<TextBlock HorizontalAlignment="Center" x:Name="InstName" Grid.Column="1" Text="{Binding InstanceName}"></TextBlock>
<TextBlock HorizontalAlignment="Center" Grid.Column="2" Text="{Binding Entries, StringFormat={}{0} files}"></TextBlock>
<TextBlock HorizontalAlignment="Center" Grid.Column="3" Text="{Binding PrettySize}"></TextBlock>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
<ProgressBar Margin="0 2 0 2" Value="{Binding Progress}" MinHeight="20"></ProgressBar>
<TextBlock Text="{Binding HeaderText}"></TextBlock>
</StackPanel>
</Border>
</Window>
+32
View File
@@ -0,0 +1,32 @@
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.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WPFLinkTool;
namespace WPFLinkTool
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SharedViewModel shared = new();
DataContext = new MainWindowViewModel(shared);
}
}
}
@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Forms;
namespace WPFLinkTool
{
public class AddInstanceViewModel : ViewModelBase
{
public readonly SharedViewModel Shared;
public bool IsCopyChecked { get; set; } = true;
private double _progress;
public double Progress
{
get
{
return _progress;
}
set
{
_progress = value;
OnPropertyChanged(nameof(Progress));
}
}
public string InstanceName { get; set; }
public string DataSource { get; set; }
private string _statusText;
public string StatusText
{
get
{
return _statusText;
}
set
{
_statusText = value;
OnPropertyChanged(nameof(StatusText));
}
}
public RelayCommand CalculateFilesCommand { get; private set; }
public RelayCommand OpenBrowseDialog { get; private set; }
public ICommand AddInstanceCommand { get; }
public AddInstanceViewModel(SharedViewModel shared)
{
Shared = shared;
InstanceName = "";
DataSource = "";
OpenBrowseDialog = new(OpenFolderBrowser);
AddInstanceCommand = new AddInstanceCommand(this, (ex) => StatusText = ex.Message);
}
public void OpenFolderBrowser(object i)
{
FolderBrowserDialog dialog = new();
dialog.ShowDialog();
DataSource = dialog.SelectedPath;
OnPropertyChanged("DataSource");
dialog.Dispose();
}
}
}
@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using static WPFLinkTool.Global;
namespace WPFLinkTool
{
public class AddInstanceCommand : AsyncCommandBase
{
private readonly AddInstanceViewModel vm;
public AddInstanceCommand(AddInstanceViewModel addInstanceViewModel, Action<Exception> onException) : base(onException)
{
vm = addInstanceViewModel;
}
protected override async Task ExecuteAsync(object parameter)
{
if (vm.InstanceName != string.Empty && vm.DataSource != string.Empty && IsUniqueName(vm.InstanceName))
{
IsExecuting = true;
vm.Progress = 0;
// Create a list of InstanceFileInfos
List<InstanceFileInfo> fileInfos = new();
long instanceSize = 0;
// Enumerate files
vm.StatusText = "Enumerating files...";
DirectoryInfo dir = new(vm.DataSource);
var files = dir.EnumerateFiles("", SearchOption.AllDirectories);
int already = 0;
// Calculate progress step
double progressStep = 100D / files.Count();
foreach (var file in files)
{
// Hash and make file infos
vm.StatusText = $"Hashing {file.FullName}";
string hash = await Task.Run(() => GetMD5Checksum(file.FullName));
InstanceFileInfo inFile = new(file.Name, hash + file.Extension,
file.DirectoryName.Replace(vm.DataSource, ""), file.Length);
instanceSize += file.Length;
// Update the progress bar
vm.Progress += progressStep;
// Add file info to the list
fileInfos.Add(inFile);
// Check if file exists and move/copy
if (!File.Exists(dbDir + @"\" + hash + file.Extension))
{
if (vm.IsCopyChecked)
{
vm.StatusText = $"Copying {file.Name}";
await Task.Run(() => File.Copy(file.FullName, dbDir + @"\" + hash + file.Extension));
}
else
{
vm.StatusText = $"Moving {file.Name}";
await Task.Run(() => File.Move(file.FullName, dbDir + @"\" + hash + file.Extension));
}
}
else already++;
}
// Create a DataInstance and add to DBInfo
DataInstance instance = new(vm.InstanceName, fileInfos, fileInfos.Count, instanceSize);
vm.Shared.Info.InstanceList.Add(instance);
vm.Shared.Info.SaveToXml();
vm.StatusText = $"Done. {instance.InstanceName} added with {instance.Entries} files and a size of {instance.PrettySize} \n" +
$"{already} files already exist.";
IsExecuting = false;
}
else
{
MessageBox.Show("Empty fields or duplicate instance name.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public string GetMD5Checksum(string filename)
{
using var md5 = MD5.Create();
using var stream = File.OpenRead(filename);
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "");
}
public bool IsUniqueName(string instancename)
{
List<string> names = new();
List<string> namesAdd = new();
foreach (var instance in vm.Shared.Info.InstanceList)
{
names.Add(instance.InstanceName);
}
namesAdd = names;
namesAdd.Add(instancename);
if (names.Count == namesAdd.Distinct().Count())
return true;
else return false;
}
}
}
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace WPFLinkTool
{
public abstract class AsyncCommandBase : ICommand
{
private readonly Action<Exception> _onException;
private bool _isExecuting;
public bool IsExecuting
{
get
{
return _isExecuting;
}
set
{
_isExecuting = value;
CanExecuteChanged?.Invoke(this, new EventArgs());
}
}
public event EventHandler CanExecuteChanged;
public AsyncCommandBase(Action<Exception> onException)
{
_onException = onException;
}
public bool CanExecute(object parameter)
{
return !IsExecuting;
}
public async void Execute(object parameter)
{
IsExecuting = true;
try
{
await ExecuteAsync(parameter);
}
catch (Exception ex)
{
_onException?.Invoke(ex);
}
IsExecuting = false;
}
protected abstract Task ExecuteAsync(object parameter);
}
}
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static WPFLinkTool.Global;
namespace WPFLinkTool
{
class DeleteUnusedCommand : AsyncCommandBase
{
private readonly MainWindowViewModel vm;
public DeleteUnusedCommand(MainWindowViewModel viewModel, Action<Exception> onException) : base(onException)
{
vm = viewModel;
}
protected override async Task ExecuteAsync(object parameter)
{
IsExecuting = true;
vm.UIEnabled = false;
HashSet<string> dBFiles = new();
DirectoryInfo dir = new(dbDir);
foreach (var file in dir.GetFiles())
{
dBFiles.Add(file.Name);
}
foreach (var instance in vm.Shared.Info.InstanceList)
{
foreach (var file in instance.InstanceFiles)
{
dBFiles.Remove(file.HashedFileName);
}
}
double progressStep = 100D / dBFiles.Count;
var prompt = MessageBox.Show($"Found {dBFiles.Count} unused files. Delete?", "Delete unused files",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (prompt == DialogResult.Yes)
{
foreach (var file in dBFiles)
{
await Task.Run(() => File.Delete(dbDir + @"\" + file));
vm.Progress += progressStep;
}
}
await Task.Run(() => vm.UpdateDBSize());
vm.Progress = 0;
vm.UIEnabled = true;
IsExecuting = false;
}
}
}
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static WPFLinkTool.Global;
namespace WPFLinkTool
{
public class MakeHardLinksCommand : AsyncCommandBase
{
private readonly MainWindowViewModel vm;
public MakeHardLinksCommand(MainWindowViewModel viewmodel, Action<Exception> onException) : base(onException)
{
vm = viewmodel;
}
protected override async Task ExecuteAsync(object parameter)
{
IsExecuting = true;
vm.UIEnabled = false;
string selInst = vm.SelectedInstance;
var selectedInstance = (from inst in vm.Shared.Info.InstanceList
where inst.InstanceName == selInst
select inst).Single();
var prompt = MessageBox.Show($"Creating hard links from {selectedInstance.InstanceName}.\nProceed to link target selection?", "Make hard links", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (prompt == DialogResult.Yes)
{
FolderBrowserDialog dialog = new();
if (dialog.ShowDialog() == DialogResult.OK)
{
string target = dialog.SelectedPath;
var uniqueFolders = (from folders in selectedInstance.InstanceFiles
where folders.Location != string.Empty
select folders.Location).Distinct();
double progressStep = 100D / (selectedInstance.InstanceFiles.Count + uniqueFolders.Count());
foreach (var folder in uniqueFolders)
{
if (!Directory.Exists(target + folder))
{
await Task.Run(() => Directory.CreateDirectory(target + folder));
}
vm.Progress += progressStep;
}
foreach (var file in selectedInstance.InstanceFiles)
{
if (!File.Exists(target + file.Location + @"\" + file.OriginalFileName))
{
await Task.Run(() => CreateHardLink(target + file.Location + @"\" + file.OriginalFileName,
dbDir + @"\" + file.HashedFileName, IntPtr.Zero));
}
vm.Progress += progressStep;
}
}
}
vm.Progress = 0;
vm.UIEnabled = true;
IsExecuting = false;
}
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
static extern bool CreateHardLink(
string lpFileName,
string lpExistingFileName,
IntPtr lpSecurityAttributes
);
}
}
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace WPFLinkTool
{
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new NullReferenceException("execute");
_execute = execute;
_canExecute = canExecute;
}
public RelayCommand(Action<object> execute) : this(execute, null)
{
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute.Invoke(parameter);
}
}
}
@@ -0,0 +1,212 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;
using System.Xml;
using System.Xml.Serialization;
using static WPFLinkTool.Global;
namespace WPFLinkTool
{
public class MainWindowViewModel : ViewModelBase
{
public readonly SharedViewModel Shared;
private string _dBSize;
public string DBSize
{
get
{
return _dBSize;
}
set
{
_dBSize = value;
OnPropertyChanged(nameof(DBSize));
}
}
private string _sumSize;
public string SumSize
{
get
{
return _sumSize;
}
set
{
_sumSize = value;
OnPropertyChanged(nameof(SumSize));
}
}
private bool _linkButtonEnabled = false;
public bool LinkButtonEnabled
{
get
{
return _linkButtonEnabled;
}
set
{
_linkButtonEnabled = value;
OnPropertyChanged(nameof(LinkButtonEnabled));
}
}
private bool _uIEnabled = true;
public bool UIEnabled
{
get
{
return _uIEnabled;
}
set
{
_uIEnabled = value;
OnPropertyChanged(nameof(UIEnabled));
}
}
private double _progress;
public double Progress
{
get
{
return _progress;
}
set
{
_progress = value;
OnPropertyChanged(nameof(Progress));
}
}
private string _headerText;
public string HeaderText
{
get
{
return _headerText;
}
set
{
_headerText = value;
OnPropertyChanged(nameof(HeaderText));
}
}
private string _selectedInstance;
public string SelectedInstance
{
get
{
return _selectedInstance;
}
set
{
_selectedInstance = value;
OnPropertyChanged(nameof(SelectedInstance));
}
}
public ObservableCollection<DataInstance> InstanceList
{
get
{
ObservableCollection<DataInstance> list = new();
foreach (var instance in Shared.Info.InstanceList)
{
list.Add(instance);
}
return list;
}
}
public RelayCommand OpenAddInstanceWindow { get; private set; }
public RelayCommand SelectedInstanceCommand { get; private set; }
public RelayCommand DeleteInstanceCommand { get; private set; }
public ICommand MakeHardLinksCommand { get; private set; }
public ICommand DeleteUnusedCommand { get; private set; }
public MainWindowViewModel(SharedViewModel shared)
{
if (!Directory.Exists(dbDir))
Directory.CreateDirectory(dbDir);
Shared = shared;
OpenAddInstanceWindow = new(OpenInstanceWindow);
SelectedInstanceCommand = new(SetSelectedRadioButton);
DeleteInstanceCommand = new(DeleteInstance);
MakeHardLinksCommand = new MakeHardLinksCommand(this, (ex) => HeaderText = ex.Message);
DeleteUnusedCommand = new DeleteUnusedCommand(this, (ex) => HeaderText = ex.Message);
LoadDBInfo();
Task.Run(() => UpdateDBSize());
Task.Run(() => UpdateSumSize());
}
private void LoadDBInfo()
{
if (!File.Exists(DBInfoPath))
{
Shared.Info = new();
}
else
{
XmlSerializer serializer = new(typeof(DBInfo));
FileStream fs = new(DBInfoPath, FileMode.Open);
XmlReader reader = XmlReader.Create(fs);
Shared.Info = (DBInfo)serializer.Deserialize(reader);
}
}
public void OpenInstanceWindow(object o)
{
AddInstanceDialog dialog = new(Shared);
dialog.ShowDialog();
OnPropertyChanged(nameof(InstanceList));
LinkButtonEnabled = false;
Task.Run(() => UpdateDBSize());
Task.Run(() => UpdateSumSize());
}
public void SetSelectedRadioButton(object o)
{
SelectedInstance = (string)o;
LinkButtonEnabled = true;
}
public void DeleteInstance(object o)
{
var prompt = MessageBox.Show($"Delete {SelectedInstance}?", "Delete instance", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (prompt == DialogResult.Yes)
{
DataInstance selected = (from inst in Shared.Info.InstanceList
where inst.InstanceName == SelectedInstance
select inst).Single();
Shared.Info.InstanceList.Remove(selected);
Shared.Info.SaveToXml();
LinkButtonEnabled = false;
UpdateSumSize();
OnPropertyChanged(nameof(InstanceList));
}
}
public void UpdateDBSize()
{
DirectoryInfo dir = new(dbDir);
long size = 0;
foreach (var file in dir.GetFiles())
{
size += file.Length;
}
DBSize = ReadableSize(size);
}
public void UpdateSumSize()
{
long size = 0;
foreach (var instance in Shared.Info.InstanceList)
{
size += instance.Size;
}
SumSize = ReadableSize(size);
}
}
}
+25
View File
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFLinkTool
{
public class SharedViewModel : ViewModelBase
{
private DBInfo _info;
public DBInfo Info
{
get
{
return _info;
}
set
{
_info = value;
OnPropertyChanged(nameof(Info));
}
}
}
}
+16
View File
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
namespace WPFLinkTool
{
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
+10
View File
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
</Project>