diff --git a/Tests/Controller/SettingsTest.cs b/Tests/Controller/SettingsTest.cs index 7395825..912992c 100755 --- a/Tests/Controller/SettingsTest.cs +++ b/Tests/Controller/SettingsTest.cs @@ -50,21 +50,5 @@ namespace Tests.Controller ((Items)clone.Elements[1]).Content, "Items content"); } - - [Test] - public void PersistSettings() - { - string name = "hello world"; - Settings persisting = new Settings(name, new List() { new Items() }); - persisting.ReferenceStyle = zaaReloaded2.Formatter.ReferenceStyle.IfSpecialItem; - MemoryStream s = new MemoryStream(); - persisting.Persist(s); - s.Position = 0; - Settings retrieved = Settings.Unpersist(s); - - Assert.AreEqual(persisting.Name, retrieved.Name, "Name"); - Assert.AreEqual(persisting.ReferenceStyle, retrieved.ReferenceStyle, "ReferenceStyle"); - - } } } diff --git a/zaaReloaded2/Controller/Settings.cs b/zaaReloaded2/Controller/Settings.cs index 46eb1b4..8a965d9 100755 --- a/zaaReloaded2/Controller/Settings.cs +++ b/zaaReloaded2/Controller/Settings.cs @@ -24,6 +24,7 @@ using zaaReloaded2.Controller.Elements; using System.IO; using System.Text.RegularExpressions; using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Soap; namespace zaaReloaded2.Controller { @@ -36,34 +37,34 @@ namespace zaaReloaded2.Controller #region Persistence /// - /// Custom serialization method that writes this settings - /// to a human-readable text file. + /// Deserializes a Settings object from SOAP XML that is read from a file. /// - /// - public void Persist(Stream stream) + /// File to read. + /// Deserialized Settings object with new unique ID. + /// if the file does not contain + /// SOAP XML that can be deserialized to a Settings object. + public static Settings LoadFromFile(string fileName) { - StreamWriter w = new StreamWriter(stream); - w.WriteLine(String.Format("[{0}]", Name)); - - w.WriteLine(ReferenceStyle.ToString()); - w.Flush(); + StreamReader reader = new StreamReader(fileName); + SoapFormatter formatter = new SoapFormatter(); + Settings settings = formatter.Deserialize(reader.BaseStream) as Settings; + if (settings == null) + { + throw new InvalidDataException("Datei enthält keine Stil-Daten oder ist beschädigt."); + } + settings.Uid = Guid.NewGuid(); + return settings; } - public static Settings Unpersist(Stream stream) + /// + /// Serializes a Settings object to SOAP XML that is written to a file. + /// + /// File to write to. + public void SaveToFile(string fileName) { - StreamReader r = new StreamReader(stream); - string line = r.ReadLine(); - Match m = _persistenceHeaderRegex.Match(line); - if (!m.Success) - throw new InvalidDataException("Settings header line does not match expected format."); - - Settings settings = new Settings(); - settings.Name = m.Groups["name"].Value; - - line = r.ReadLine(); - settings.ReferenceStyle = (ReferenceStyle)Enum.Parse(typeof(ReferenceStyle), line); - - return settings; + StreamWriter writer = new StreamWriter(fileName); + SoapFormatter formatter = new SoapFormatter(); + formatter.Serialize(writer.BaseStream, this); } #endregion diff --git a/zaaReloaded2/Properties/Settings.Designer.cs b/zaaReloaded2/Properties/Settings.Designer.cs index 625959a..bf379f7 100755 --- a/zaaReloaded2/Properties/Settings.Designer.cs +++ b/zaaReloaded2/Properties/Settings.Designer.cs @@ -291,5 +291,17 @@ namespace zaaReloaded2.Properties { return ((int)(this["SerializationVersion"])); } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string ImportExportPath { + get { + return ((string)(this["ImportExportPath"])); + } + set { + this["ImportExportPath"] = value; + } + } } } diff --git a/zaaReloaded2/Properties/Settings.settings b/zaaReloaded2/Properties/Settings.settings index e5ba5b7..45f429b 100755 --- a/zaaReloaded2/Properties/Settings.settings +++ b/zaaReloaded2/Properties/Settings.settings @@ -89,5 +89,8 @@ 1 + + + \ No newline at end of file diff --git a/zaaReloaded2/ViewModels/IoErrorViewModel.cs b/zaaReloaded2/ViewModels/IoErrorViewModel.cs new file mode 100755 index 0000000..ad26bfd --- /dev/null +++ b/zaaReloaded2/ViewModels/IoErrorViewModel.cs @@ -0,0 +1,46 @@ +/* IoErrorViewModel.cs + * part of zaaReloaded2 + * + * Copyright 2015 Daniel Kraus + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Bovender.Mvvm.ViewModels; + +namespace zaaReloaded2.ViewModels +{ + /// + /// Simple view model for I/O error messages, for use in conjunction + /// with Bovender's ShowViewDialogAction and zaaReloaded2.Views.IoErrorView. + /// + class IoErrorViewModel : ViewModelBase + { + public Exception Exception { get; private set; } + + public string Message { get { return Exception.Message; } } + + public IoErrorViewModel(Exception e) + { + Exception = e; + } + + public override object RevealModelObject() + { + return Exception; + } + } +} diff --git a/zaaReloaded2/ViewModels/SettingsRepositoryViewModel.cs b/zaaReloaded2/ViewModels/SettingsRepositoryViewModel.cs index c398e57..837e7fa 100755 --- a/zaaReloaded2/ViewModels/SettingsRepositoryViewModel.cs +++ b/zaaReloaded2/ViewModels/SettingsRepositoryViewModel.cs @@ -24,6 +24,8 @@ using Bovender.Mvvm.ViewModels; using Bovender.Mvvm.Messaging; using zaaReloaded2.Controller; using System.Collections.ObjectModel; +using System.Runtime.Serialization.Formatters.Soap; +using System.IO; namespace zaaReloaded2.ViewModels { @@ -134,6 +136,33 @@ namespace zaaReloaded2.ViewModels } } + public DelegatingCommand ExportSettingsCommand + { + get + { + if (_exportSettingsCommand == null) + { + _exportSettingsCommand = new DelegatingCommand( + param => DoExportSettings(), + param => CanExportSettings()); + } + return _exportSettingsCommand; + } + } + public DelegatingCommand ImportSettingsCommand + { + get + { + if (_importSettingsCommand == null) + { + _importSettingsCommand = new DelegatingCommand( + param => DoImportSettings(), + param => CanImportSettings()); + } + return _importSettingsCommand; + } + } + #endregion #region Messages @@ -186,6 +215,54 @@ namespace zaaReloaded2.ViewModels } } + public Message ChooseExportFileNameMessage + { + get + { + if (_chooseExportFileNameMessage == null) + { + _chooseExportFileNameMessage = new Message(); + } + return _chooseExportFileNameMessage; + } + } + + public Message ChooseImportFileNameMessage + { + get + { + if (_chooseImportFileNameMessage == null) + { + _chooseImportFileNameMessage = new Message(); + } + return _chooseImportFileNameMessage; + } + } + + public Message ExportErrorMessage + { + get + { + if (_exportErrorMessage == null) + { + _exportErrorMessage = new Message(); + } + return _exportErrorMessage; + } + } + + public Message ImportErrorMessage + { + get + { + if (_importErrorMessage == null) + { + _importErrorMessage = new Message(); + } + return _importErrorMessage; + } + } + #endregion #region Constructors @@ -334,6 +411,86 @@ namespace zaaReloaded2.ViewModels SettingsList.Add(settingsViewModel); } + void DoExportSettings() + { + if (CanExportSettings()) + { + ChooseExportFileNameMessage.Send( + new FileNameMessageContent(SuggestImportExportPath(), FILE_FILTER), + msg => ConfirmExportSettings(msg)); + } + } + + bool CanExportSettings() + { + return LastSelected != null && LastSelected.IsSelected && !IsDefaultSettings(); + } + + void ConfirmExportSettings(FileNameMessageContent message) + { + if (message.Confirmed) + { + Properties.Settings.Default.ImportExportPath = message.Value; + Properties.Settings.Default.Save(); + Settings settings = LastSelected.RevealModelObject() as Settings; + try + { + settings.SaveToFile(message.Value); + } + catch (Exception e) + { + ExportErrorMessage.Send( + new ViewModelMessageContent(new IoErrorViewModel(e)) + ); + } + } + } + + void DoImportSettings() + { + ChooseImportFileNameMessage.Send( + new FileNameMessageContent(SuggestImportExportPath(), FILE_FILTER), + msg => ConfirmImportSettings(msg)); + } + + bool CanImportSettings() + { + return true; + } + + void ConfirmImportSettings(FileNameMessageContent message) + { + if (message.Confirmed) + { + Properties.Settings.Default.ImportExportPath = message.Value; + Properties.Settings.Default.Save(); + try + { + Settings settings = Settings.LoadFromFile(message.Value); + AddSettingsViewModel(new SettingsViewModel(settings)); + } + catch (Exception e) + { + ImportErrorMessage.Send( + new ViewModelMessageContent(new IoErrorViewModel(e)) + ); + } + } + } + + string SuggestImportExportPath() + { + string path = Properties.Settings.Default.ImportExportPath; + if (String.IsNullOrEmpty(path)) + { + return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + } + else + { + return path; + } + } + #endregion #region Implementation of ViewModelBase @@ -354,10 +511,26 @@ namespace zaaReloaded2.ViewModels DelegatingCommand _deleteSettingsCommand; DelegatingCommand _resetSettingsCommand; DelegatingCommand _copySettingsCommand; + DelegatingCommand _exportSettingsCommand; + DelegatingCommand _importSettingsCommand; Message _confirmDeleteSettingsMessage; Message _confirmResetSettingsMessage; Message _editSettingsMessage; Message _useSettingsMessage; + Message _chooseExportFileNameMessage; + Message _chooseImportFileNameMessage; + Message _exportErrorMessage; + Message _importErrorMessage; + + #endregion + + #region Constant + + /// + /// File filter that is used for the import and export + /// of settings. + /// + const string FILE_FILTER = "zaaReloaded-Stildatei (*.zaaReloaded)|*.zaaReloaded"; #endregion } diff --git a/zaaReloaded2/Views/IoErrorView.xaml b/zaaReloaded2/Views/IoErrorView.xaml new file mode 100755 index 0000000..3e52132 --- /dev/null +++ b/zaaReloaded2/Views/IoErrorView.xaml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + +