diff --git a/csharp/GUI/AboutDialog.xaml b/csharp/GUI/AboutDialog.xaml index 1244ce2..31bb45e 100644 --- a/csharp/GUI/AboutDialog.xaml +++ b/csharp/GUI/AboutDialog.xaml @@ -29,12 +29,12 @@ - + - + @@ -48,13 +48,13 @@ - + - + diff --git a/csharp/GUI/App.xaml b/csharp/GUI/App.xaml index dc439c3..4527961 100644 --- a/csharp/GUI/App.xaml +++ b/csharp/GUI/App.xaml @@ -12,6 +12,7 @@ + diff --git a/csharp/GUI/Configurations.cs b/csharp/GUI/Configurations.cs new file mode 100644 index 0000000..d70094e --- /dev/null +++ b/csharp/GUI/Configurations.cs @@ -0,0 +1,138 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Windows; +using Tomlet; +using Tomlet.Attributes; +using Tomlet.Models; + +namespace OpenSvip.GUI.Config +{ + public class AppConfig + { + private const string CONFIG_FOLDER = "Config"; + + private const string CONFIG_FILENAME = "Configurations.toml"; + + private static readonly string ActualConfigFolder = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), CONFIG_FOLDER); + + private static readonly string ActualConfigFile = Path.Combine(ActualConfigFolder, CONFIG_FILENAME); + + [TomlProperty("Restoration")] + public Properties Properties { get; set; } = new Properties(); + + [TomlProperty("Preference")] + public Settings Settings { get; set; } = new Settings(); + + static AppConfig() + { + TomletMain.RegisterMapper( + rect => new TomlArray { rect.Left, rect.Top, rect.Width, rect.Height }, + tomlValue => + { + if (!(tomlValue is TomlArray tomlArray)) + { + return new Rect(); + } + try + { + var arr = tomlArray.Select(val => ((TomlDouble)val).Value).ToArray(); + return new Rect(arr[0], arr[1], arr[2], arr[3]); + } + catch + { + return new Rect(); + } + }); + } + + public static AppConfig LoadFromFile() + { + try + { + var stream = new FileStream(ActualConfigFile, FileMode.Open, FileAccess.Read); + var reader = new StreamReader(stream); + var config = TomletMain.To(reader.ReadToEnd()); + reader.Close(); + stream.Close(); + return config; + } + catch + { + return new AppConfig(); + } + } + + public void SaveToFile() + { + try + { + Directory.CreateDirectory(ActualConfigFolder); + var stream = new FileStream(ActualConfigFile, FileMode.Create, FileAccess.Write); + var writer = new StreamWriter(stream); + writer.Write(TomletMain.TomlStringFrom(this)); + writer.Flush(); + stream.Flush(); + writer.Close(); + stream.Close(); + } + catch + { + // ignored + } + } + } + + public class Information + { + public string Version { get; set; } = "1.0.6 (Preview)"; + + public string FrameworkVersion { get; set; } = "1.2.2"; + + public string Author { get; set; } = "YQ之神"; + + public string AuthorHomePage { get; set; } = "https://space.bilibili.com/102844209"; + + public string GitHubRepository { get; set; } = "https://github.com/yqzhishen/opensvip"; + } + + [TomlDoNotInlineObject] + public class Properties + { + public Rect MainRestoreBounds { get; set; } = new Rect(); + + public WindowState MainWindowState { get; set; } = WindowState.Normal; + } + + public class Settings + { + public string ImportPluginId { get; set; } + + public string ExportPluginId { get; set; } + + public bool AutoDetectFormat { get; set; } = true; + + public bool AutoResetTasks { get; set; } = true; + + public bool AutoExtension { get; set; } = true; + + public bool OpenExportFolder { get; set; } = false; + + public OverwriteOptions OverwriteOption { get; set; } = OverwriteOptions.Overwrite; + + public ExportPaths DefaultExportPath { get; set; } = ExportPaths.Unset; + + public string[] CustomExportPaths { get; set; } = Array.Empty(); + } + + public enum OverwriteOptions + { + Overwrite, Skip, Ask + } + + public enum ExportPaths + { + Unset, Source, Desktop, Custom + } +} diff --git a/csharp/GUI/MainWindow.xaml b/csharp/GUI/MainWindow.xaml index fe9337b..8bda775 100644 --- a/csharp/GUI/MainWindow.xaml +++ b/csharp/GUI/MainWindow.xaml @@ -5,6 +5,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:OpenSvip.GUI" + xmlns:config="clr-namespace:OpenSvip.GUI.Config" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" Title="OpenSVIP - 歌声合成工程文件转换器(预览版本)" @@ -38,11 +39,11 @@ - - None - Source - Desktop - Custom + + Unset + Source + Desktop + Custom + SelectedIndex="{Binding DefaultExportPath, Converter={StaticResource IndexToEnumValueConverter}, ConverterParameter={x:Type config:ExportPaths}}"/> @@ -386,7 +387,7 @@ DragLeave="FileMaskPanel_UnFocus"> + @@ -531,7 +533,7 @@ + Width="{Binding ActualWidth, ElementName=ConverterOptionsCard, Converter={StaticResource DoubleConstantSubConverter}, ConverterParameter=64}"> @@ -554,7 +556,7 @@ - + @@ -582,7 +584,7 @@ - + @@ -654,6 +656,7 @@ + SelectedIndex="{Binding OverWriteOption, Converter={StaticResource IndexToEnumValueConverter}, ConverterParameter={x:Type config:OverwriteOptions}}"> diff --git a/csharp/GUI/MainWindow.xaml.cs b/csharp/GUI/MainWindow.xaml.cs index bf039e0..f32e159 100644 --- a/csharp/GUI/MainWindow.xaml.cs +++ b/csharp/GUI/MainWindow.xaml.cs @@ -2,7 +2,6 @@ using System.Windows.Controls; using System.Windows.Media.Animation; using System; -using MaterialDesignThemes.Wpf; using System.Windows; using System.Linq; using System.Collections.Generic; @@ -12,8 +11,7 @@ using System.Diagnostics; using Microsoft.WindowsAPICodePack.Dialogs; using System.Windows.Input; -using System.Reflection; -using Newtonsoft.Json; +using OpenSvip.GUI.Config; namespace OpenSvip.GUI { @@ -27,22 +25,39 @@ public partial class MainWindow public MainWindow() { InitializeComponent(); - try - { - FileStream stream = new FileStream( - Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Configurations.json"), - FileMode.Open, - FileAccess.Read); - StreamReader reader = new StreamReader(stream); - Model = JsonConvert.DeserializeObject(reader.ReadToEnd()); - reader.Close(); - stream.Close(); + + var config = AppConfig.LoadFromFile(); + + var properties = config.Properties; + var bounds = properties.MainRestoreBounds; + if (bounds.Width > 0 && bounds.Height > 0) + { + WindowState = WindowState.Normal; + Left = bounds.Left; + Top = bounds.Top; + Width = bounds.Width; + Height = bounds.Height; } - catch (Exception) + WindowState = properties.MainWindowState; + + var settings = config.Settings; + Model = new AppModel + { + AutoDetectFormat = settings.AutoDetectFormat, + AutoResetTasks = settings.AutoResetTasks, + AutoExtension = settings.AutoExtension, + OpenExportFolder = settings.OpenExportFolder, + OverWriteOption = settings.OverwriteOption, + DefaultExportPath = settings.DefaultExportPath + }; + Model.SelectedInputPluginIndex = settings.ImportPluginId == null ? -1 : Model.Plugins.FindIndex(plugin => plugin.Identifier.Equals(settings.ImportPluginId)); + Model.SelectedOutputPluginIndex = settings.ExportPluginId == null ? -1 : Model.Plugins.FindIndex(plugin => plugin.Identifier.Equals(settings.ExportPluginId)); + foreach (var path in settings.CustomExportPaths) { - Model = new AppModel(); + Model.CustomExportPaths.Add(path); } DataContext = Model; + var formats = Model.Formats; foreach (var str in formats) { @@ -98,7 +113,7 @@ private void AddConverterTasks(IEnumerable filenames) var newFilenames = filenames .Where(filename => Model.TaskList.All(task => task.ImportPath != filename)) .ToArray(); - if (Model.DefaultExportPath == DefaultExport.None && !Model.TaskList.Any() && filenames.Any()) + if (Model.DefaultExportPath == ExportPaths.Unset && !Model.TaskList.Any() && filenames.Any()) { Model.ExportPath = Path.GetDirectoryName(filenames.First()); } @@ -172,7 +187,7 @@ private void ExecuteTasks() var askBeforeOverwrite = Model.OverWriteOption == OverwriteOptions.Ask; foreach (var task in Model.TaskList) { - task.ExportFolder = Model.DefaultExportPath == DefaultExport.Source && string.IsNullOrWhiteSpace(Model.ExportPath) ? task.ImportDirectory : Model.ExportPath; + task.ExportFolder = Model.DefaultExportPath == ExportPaths.Source && string.IsNullOrWhiteSpace(Model.ExportPath) ? task.ImportDirectory : Model.ExportPath; var exportPath = Path.Combine(task.ExportFolder, task.ExportTitle + Model.ExportExtension); if (File.Exists(exportPath)) { @@ -233,7 +248,7 @@ private void ExecuteTasks() if (Model.OpenExportFolder) { var openFolder = Model.ExportPath; - if (Model.DefaultExportPath == DefaultExport.Source) + if (Model.DefaultExportPath == ExportPaths.Source) { openFolder = Model.TaskList[0].ImportDirectory; foreach (var task in Model.TaskList.Skip(1)) @@ -550,7 +565,7 @@ private void BrowseExportFolderButton_Click(object sender, RoutedEventArgs e) private void StartExecutionButton_Click(object sender, RoutedEventArgs e) { - if (String.IsNullOrWhiteSpace(Model.ExportPath) && Model.DefaultExportPath != DefaultExport.Source) + if (String.IsNullOrWhiteSpace(Model.ExportPath) && Model.DefaultExportPath != ExportPaths.Source) { BrowseExportFolderButton_Click(sender, e); if (String.IsNullOrWhiteSpace(Model.ExportPath)) @@ -581,23 +596,26 @@ private void BrowseAndExportMenu_Click(object sender, RoutedEventArgs e) private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { - try - { - FileStream stream = new FileStream( - Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Configurations.json"), - FileMode.Create, - FileAccess.Write); - StreamWriter writer = new StreamWriter(stream); - writer.Write(JsonConvert.SerializeObject(Model, Formatting.Indented)); - writer.Flush(); - stream.Flush(); - writer.Close(); - stream.Close(); - } - catch (Exception) + new AppConfig { - // ignored - } + Properties = + { + MainRestoreBounds = RestoreBounds, + MainWindowState = WindowState + }, + Settings = + { + ImportPluginId = Model.SelectedInputPlugin?.Identifier, + ExportPluginId = Model.SelectedOutputPlugin?.Identifier, + AutoDetectFormat = Model.AutoDetectFormat, + AutoResetTasks = Model.AutoResetTasks, + AutoExtension = Model.AutoExtension, + OpenExportFolder = Model.OpenExportFolder, + OverwriteOption = Model.OverWriteOption, + DefaultExportPath = Model.DefaultExportPath, + CustomExportPaths = Model.CustomExportPaths.ToArray() + } + }.SaveToFile(); } } } diff --git a/csharp/GUI/OpenSvip.GUI.csproj b/csharp/GUI/OpenSvip.GUI.csproj index 57e30a1..3277fa7 100644 --- a/csharp/GUI/OpenSvip.GUI.csproj +++ b/csharp/GUI/OpenSvip.GUI.csproj @@ -65,10 +65,6 @@ ..\packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll True - - ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - @@ -82,6 +78,9 @@ 4.0 + + ..\packages\Samboy063.Tomlet.3.1.3\lib\net35\Tomlet.dll + @@ -95,6 +94,7 @@ AboutDialog.xaml + FileOverwriteDialog.xaml @@ -153,6 +153,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -197,6 +201,10 @@ {1a025cf4-6ce6-42f9-ad09-16e56d840d95} OpenSvip.Framework + + {c0982090-a08e-45b8-953a-6d1750a69cdd} + OpenSvip.Library + {f0cf4e57-33f4-4a63-a45f-69727058c24a} OpenSvip.Model diff --git a/csharp/GUI/OptionTreeViewItem.xaml b/csharp/GUI/OptionTreeViewItem.xaml index e4b30e2..65a8f8c 100644 --- a/csharp/GUI/OptionTreeViewItem.xaml +++ b/csharp/GUI/OptionTreeViewItem.xaml @@ -61,7 +61,7 @@ d:DataContext="{d:DesignInstance Type=local:OptionViewModel}" DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TreeViewItem}, Path=DataContext}"> - + @@ -70,7 +70,7 @@ d:DataContext="{d:DesignInstance Type=local:OptionViewModel}" DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TreeViewItem}, Path=DataContext}"> - + @@ -79,7 +79,7 @@ d:DataContext="{d:DesignInstance Type=local:OptionViewModel}" DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TreeViewItem}, Path=DataContext}"> - + @@ -102,8 +102,8 @@ DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TreeViewItem}, Path=DataContext}"> diff --git a/csharp/GUI/Properties/AssemblyInfo.cs b/csharp/GUI/Properties/AssemblyInfo.cs index a436afe..a8d6bac 100644 --- a/csharp/GUI/Properties/AssemblyInfo.cs +++ b/csharp/GUI/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("1.0.6.1")] +[assembly: AssemblyFileVersion("1.0.6.1")] \ No newline at end of file diff --git a/csharp/GUI/ScrollBarDictionary.xaml b/csharp/GUI/ScrollBarDictionary.xaml new file mode 100644 index 0000000..56ed74c --- /dev/null +++ b/csharp/GUI/ScrollBarDictionary.xaml @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/csharp/GUI/TaskListViewItem.xaml b/csharp/GUI/TaskListViewItem.xaml index 0244be1..4bfa28f 100644 --- a/csharp/GUI/TaskListViewItem.xaml +++ b/csharp/GUI/TaskListViewItem.xaml @@ -200,8 +200,8 @@ - - + + @@ -229,7 +229,7 @@ diff --git a/csharp/GUI/ViewModels.cs b/csharp/GUI/ViewModels.cs index abb8fcb..293f2d8 100644 --- a/csharp/GUI/ViewModels.cs +++ b/csharp/GUI/ViewModels.cs @@ -5,12 +5,10 @@ using System.IO; using System.Linq; using OpenSvip.Framework; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; +using OpenSvip.GUI.Config; namespace OpenSvip.GUI { - [JsonObject(MemberSerialization = MemberSerialization.OptIn)] public class AppModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; @@ -45,23 +43,14 @@ public AppModel() }); } - public string Version { get; set; } = "1.0.5 (Preview)"; + public Information Information { get; set; } = new Information(); - public string FrameworkVersion { get; set; } = "1.2.2"; - - public string Author { get; set; } = "YQ之神"; - - public string AuthorHomePage { get; set; } = "https://space.bilibili.com/102844209"; - - public string GitHubRepository { get; set; } = "https://github.com/yqzhishen/opensvip"; - - public List Plugins { get; } = PluginManager.GetAllPlugins().ToList(); + public List Plugins { get; set; } = PluginManager.GetAllPlugins().ToList(); public List Formats => Plugins.ConvertAll(plugin => $"{plugin.Format} (*.{plugin.Suffix})"); - private bool _autoDetectFormat = true; + private bool _autoDetectFormat; - [JsonProperty] public bool AutoDetectFormat { get => _autoDetectFormat; @@ -72,9 +61,8 @@ public bool AutoDetectFormat } } - private bool _autoResetTasks = true; + private bool _autoResetTasks; - [JsonProperty] public bool AutoResetTasks { get => _autoResetTasks; @@ -84,9 +72,8 @@ public bool AutoResetTasks } } - private bool _autoExtension = true; + private bool _autoExtension; - [JsonProperty] public bool AutoExtension { get => _autoExtension; @@ -106,7 +93,6 @@ public bool AutoExtension private bool _openExportFolder; - [JsonProperty] public bool OpenExportFolder { get => _openExportFolder; @@ -119,8 +105,6 @@ public bool OpenExportFolder private OverwriteOptions _overwriteOption = OverwriteOptions.Overwrite; - [JsonProperty] - [JsonConverter(typeof(StringEnumConverter))] public OverwriteOptions OverWriteOption { get => _overwriteOption; @@ -131,27 +115,25 @@ public OverwriteOptions OverWriteOption } } - private DefaultExport _defaultExportPath = DefaultExport.None; + private ExportPaths _defaultExportPath; - [JsonProperty] - [JsonConverter(typeof(StringEnumConverter))] - public DefaultExport DefaultExportPath + public ExportPaths DefaultExportPath { get => _defaultExportPath; set { _defaultExportPath = value; switch (value) { - case DefaultExport.Source: + case ExportPaths.Source: ExportPath = ""; break; - case DefaultExport.Desktop: + case ExportPaths.Desktop: ExportPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); break; - case DefaultExport.Custom: + case ExportPaths.Custom: // TODO: implement this break; - case DefaultExport.None: + case ExportPaths.Unset: default: break; } @@ -159,7 +141,6 @@ public DefaultExport DefaultExportPath } } - [JsonProperty] public ObservableCollection CustomExportPaths { get; set; } = new AsyncObservableCollection(); private int _selectedInputPluginIndex = -1; @@ -172,6 +153,7 @@ public int SelectedInputPluginIndex _selectedInputPluginIndex = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedInputPluginIndex")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedInputPlugin")); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedInputFormat")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedInputOptions")); } } @@ -179,6 +161,14 @@ public int SelectedInputPluginIndex public Plugin SelectedInputPlugin => SelectedInputPluginIndex >= 0 ? Plugins[SelectedInputPluginIndex] : null; + public string SelectedInputFormat => + SelectedInputPluginIndex >= 0 ? Plugins[SelectedInputPluginIndex].Format : null; + + public ObservableCollection SelectedInputOptions + => _selectedInputPluginIndex >= 0 ? InputOptions[_selectedInputPluginIndex] : null; + + public List> InputOptions { get; } + private int _selectedOutputPluginIndex = -1; public int SelectedOutputPluginIndex @@ -190,6 +180,7 @@ public int SelectedOutputPluginIndex ExportExtension = AutoExtension && value >= 0 ? "." + SelectedOutputPlugin.Suffix : null; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedOutputPluginIndex")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedOutputPlugin")); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedOutputFormat")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedOutputOptions")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ExportExtension")); } @@ -198,7 +189,13 @@ public int SelectedOutputPluginIndex public Plugin SelectedOutputPlugin => SelectedOutputPluginIndex >= 0 ? Plugins[SelectedOutputPluginIndex] : null; - public List> InputOptions { get; } + public string SelectedOutputFormat => + SelectedOutputPluginIndex >= 0 ? Plugins[SelectedOutputPluginIndex].Format : null; + + public ObservableCollection SelectedOutputOptions + => _selectedOutputPluginIndex >= 0 ? OutputOptions[_selectedOutputPluginIndex] : null; + + public List> OutputOptions { get; } private string _exportExtension; @@ -229,14 +226,6 @@ public string ExportExtension } } - public ObservableCollection SelectedInputOptions - => _selectedInputPluginIndex >= 0 ? InputOptions[_selectedInputPluginIndex] : null; - - public List> OutputOptions { get; } - - public ObservableCollection SelectedOutputOptions - => _selectedOutputPluginIndex >= 0 ? OutputOptions[_selectedOutputPluginIndex] : null; - public ObservableCollection TaskList { get; set; } = new AsyncObservableCollection(); private string _exportPath; @@ -388,14 +377,4 @@ public enum TaskStates { Ready, Queued, Success, Warning, Error, Skipped } - - public enum DefaultExport - { - None, Source, Desktop, Custom - } - - public enum OverwriteOptions - { - Overwrite, Skip, Ask - } } diff --git a/csharp/GUI/packages.config b/csharp/GUI/packages.config index 8c03287..3a62417 100644 --- a/csharp/GUI/packages.config +++ b/csharp/GUI/packages.config @@ -2,7 +2,7 @@ - + \ No newline at end of file