Add config import and export
This commit is contained in:
@@ -19,15 +19,17 @@
|
||||
|
||||
<Border DockPanel.Dock="Bottom" BorderThickness="1,0,0,0" Padding="0,12,0,0"
|
||||
BorderBrush="{DynamicResource AppBorderBrush}">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<WrapPanel HorizontalAlignment="Right">
|
||||
<Button Content="Save" Click="Save_Click" Margin="0,0,8,0"/>
|
||||
<Button Content="Backup Config" Click="BackupConfig_Click" Margin="0,0,8,0"/>
|
||||
<Button Content="Restore Config" Click="RestoreConfig_Click" Margin="0,0,8,0"/>
|
||||
<Button Content="Export Config" Click="ExportConfig_Click" Margin="0,0,8,0"/>
|
||||
<Button Content="Import Config" Click="ImportConfig_Click" Margin="0,0,8,0"/>
|
||||
<Button Content="Reload Config" Click="ReloadConfig_Click" Margin="0,0,8,0"/>
|
||||
<Button Content="Open Config Folder" Click="OpenConfigFolder_Click" Margin="0,0,8,0"/>
|
||||
<Button Content="About" Click="About_Click" Margin="0,0,8,0"/>
|
||||
<Button Content="Close" Click="Close_Click"/>
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
</Border>
|
||||
|
||||
<Grid>
|
||||
|
||||
@@ -636,6 +636,77 @@ public partial class MainWindow : Window
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportConfig_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (controller is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyConfigFields();
|
||||
using SaveFileDialog dialog = new()
|
||||
{
|
||||
Title = "Export launcher config",
|
||||
Filter = "JSON config files|*.json|All files|*.*",
|
||||
FileName = $"TaskbarLauncher-config-{DateTime.Now:yyyyMMdd-HHmmss}.json",
|
||||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string exportPath = ConfigService.ExportTo(dialog.FileName, controller.Config);
|
||||
StatusText.Text = $"Exported config to {exportPath}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Could not export config.\n\n{ex.Message}", "Taskbar Launcher");
|
||||
}
|
||||
}
|
||||
|
||||
private void ImportConfig_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
using OpenFileDialog dialog = new()
|
||||
{
|
||||
Title = "Import launcher config",
|
||||
Filter = "JSON config files|*.json|All files|*.*",
|
||||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBoxResult result = MessageBox.Show(
|
||||
"Import this config file and replace the current launcher config?\n\nA local backup will be created first.",
|
||||
"Taskbar Launcher",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Question);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string backupPath = ConfigService.Backup();
|
||||
ConfigService.ImportFrom(dialog.FileName);
|
||||
controller?.ReloadConfig();
|
||||
RefreshView();
|
||||
StatusText.Text = $"Imported config from {dialog.FileName}. Previous config backed up to {backupPath}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Could not import config.\n\n{ex.Message}", "Taskbar Launcher");
|
||||
}
|
||||
}
|
||||
|
||||
private List<int>? FindItemPath(LauncherItem item)
|
||||
{
|
||||
if (controller is null)
|
||||
|
||||
@@ -61,18 +61,35 @@ public static class ConfigService
|
||||
return backupPath;
|
||||
}
|
||||
|
||||
public static LauncherConfig Restore(string sourcePath)
|
||||
public static string ExportTo(string destinationPath, LauncherConfig config)
|
||||
{
|
||||
if (!File.Exists(sourcePath))
|
||||
if (string.IsNullOrWhiteSpace(destinationPath))
|
||||
{
|
||||
throw new FileNotFoundException("The selected config file was not found.", sourcePath);
|
||||
throw new ArgumentException("Choose a destination path for the exported config.", nameof(destinationPath));
|
||||
}
|
||||
|
||||
string json = File.ReadAllText(sourcePath);
|
||||
LauncherConfig config = JsonSerializer.Deserialize<LauncherConfig>(json, JsonOptions)
|
||||
?? throw new InvalidDataException("The selected config file could not be read.");
|
||||
string? destinationFolder = Path.GetDirectoryName(destinationPath);
|
||||
if (!string.IsNullOrWhiteSpace(destinationFolder))
|
||||
{
|
||||
Directory.CreateDirectory(destinationFolder);
|
||||
}
|
||||
|
||||
NormalizeDisplayModes(config);
|
||||
string json = JsonSerializer.Serialize(config, JsonOptions);
|
||||
File.WriteAllText(destinationPath, json);
|
||||
return destinationPath;
|
||||
}
|
||||
|
||||
public static LauncherConfig ImportFrom(string sourcePath)
|
||||
{
|
||||
LauncherConfig config = ReadConfigFile(sourcePath);
|
||||
Save(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
public static LauncherConfig Restore(string sourcePath)
|
||||
{
|
||||
LauncherConfig config = ReadConfigFile(sourcePath);
|
||||
Save(config);
|
||||
return config;
|
||||
}
|
||||
@@ -135,6 +152,61 @@ public static class ConfigService
|
||||
return config;
|
||||
}
|
||||
|
||||
private static LauncherConfig ReadConfigFile(string sourcePath)
|
||||
{
|
||||
if (!File.Exists(sourcePath))
|
||||
{
|
||||
throw new FileNotFoundException("The selected config file was not found.", sourcePath);
|
||||
}
|
||||
|
||||
string json = File.ReadAllText(sourcePath);
|
||||
LauncherConfig config;
|
||||
try
|
||||
{
|
||||
config = JsonSerializer.Deserialize<LauncherConfig>(json, JsonOptions)
|
||||
?? throw new InvalidDataException("The selected config file could not be read.");
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
throw new InvalidDataException("The selected file is not a valid Taskbar Launcher config.", ex);
|
||||
}
|
||||
|
||||
ValidateConfig(config);
|
||||
NormalizeDisplayModes(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
private static void ValidateConfig(LauncherConfig config)
|
||||
{
|
||||
if (config.Items is null)
|
||||
{
|
||||
throw new InvalidDataException("The selected config is missing launcher items.");
|
||||
}
|
||||
|
||||
foreach (LauncherItem item in config.Items)
|
||||
{
|
||||
ValidateItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateItem(LauncherItem item)
|
||||
{
|
||||
if (item.Children is null)
|
||||
{
|
||||
throw new InvalidDataException($"The item '{item.Title}' has an invalid children list.");
|
||||
}
|
||||
|
||||
if (!Enum.IsDefined(item.Type))
|
||||
{
|
||||
throw new InvalidDataException($"The item '{item.Title}' has an invalid type.");
|
||||
}
|
||||
|
||||
foreach (LauncherItem child in item.Children)
|
||||
{
|
||||
ValidateItem(child);
|
||||
}
|
||||
}
|
||||
|
||||
private static void NormalizeDisplayModes(LauncherConfig config)
|
||||
{
|
||||
foreach (LauncherItem item in config.Items)
|
||||
|
||||
Reference in New Issue
Block a user