using Ookii.Dialogs.Wpf;
using System;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows;
using VBASync.Localization;
namespace VBASync.WPF
{
internal sealed class MainViewModel : ViewModelBase, IDisposable
{
private readonly Action _onLoadIni;
private readonly string _lastSessionPath;
private Model.ActiveSession _activeSession;
private ChangesViewModel _changes;
private SessionViewModel _session;
private SettingsViewModel _settings;
internal MainViewModel(Model.Startup startup, Action onLoadIni)
{
Session = new SessionViewModel
{
Action = startup.Action,
AutoRun = startup.AutoRun,
FilePath = startup.FilePath,
FolderPath = startup.FolderPath
};
Settings = new SettingsViewModel
{
AddNewDocumentsToFile = startup.AddNewDocumentsToFile,
AfterExtractHookContent = startup.AfterExtractHook?.Content,
BeforePublishHookContent = startup.BeforePublishHook?.Content,
DiffTool = startup.DiffTool,
DiffToolParameters = startup.DiffToolParameters,
IgnoreEmpty = startup.IgnoreEmpty,
Language = startup.Language,
Portable = startup.Portable,
SearchRepositorySubdirectories = startup.SearchRepositorySubdirectories
};
RecentFiles = new BindingList<string>();
foreach (var recentFile in startup.RecentFiles)
{
RecentFiles.Add(recentFile);
}
_onLoadIni = onLoadIni;
_lastSessionPath = startup.LastSessionPath;
BrowseForSessionCommand = new WpfCommand(v => BrowseForSession());
LoadLastSessionCommand = new WpfCommand(v => LoadLastSession(), v => LastSessionExists());
OpenRecentCommand = new WpfCommand(v => LoadRecent((string)v));
SaveSessionCommand = new WpfCommand(v => SaveSession());
RecentFiles.ListChanged += (s, e) => OnPropertyChanged(nameof(RecentFiles));
}
public Model.ActiveSession ActiveSession => _activeSession;
public WpfCommand BrowseForSessionCommand { get; }
public ChangesViewModel Changes
{
get => _changes;
set => SetField(ref _changes, value, nameof(Changes));
}
public WpfCommand LoadLastSessionCommand { get; }
public WpfCommand OpenRecentCommand { get; }
public BindingList<string> RecentFiles { get; }
public WpfCommand SaveSessionCommand { get; }
public SessionViewModel Session
{
get => _session;
set
{
SetField(ref _session, value, nameof(Session));
RefreshActiveSession();
}
}
public SettingsViewModel Settings
{
get => _settings;
set => SetField(ref _settings, value, nameof(Settings));
}
public void AddRecentFile(string path)
{
var exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var exeDirWithTrailing = exeDir + Path.DirectorySeparatorChar.ToString();
var displayPath = Path.GetFullPath(path);
if (displayPath.StartsWith(exeDirWithTrailing))
{
displayPath = displayPath.Substring(exeDirWithTrailing.Length);
}
if (RecentFiles.Contains(displayPath))
{
RecentFiles.Remove(displayPath);
}
RecentFiles.Insert(0, displayPath);
while (RecentFiles.Count > 5)
{
RecentFiles.RemoveAt(5);
}
}
public void Dispose()
{
_activeSession?.Dispose();
}
public void LoadIni(Model.AppIniFile ini)
{
Session.Action = ini.GetActionType("General", "ActionType") ?? Model.ActionType.Extract;
Session.FolderPath = ini.GetString("General", "FolderPath");
Session.FilePath = ini.GetString("General", "FilePath");
Settings.AddNewDocumentsToFile = ini.GetBool("General", "AddNewDocumentsToFile") ?? false;
Settings.IgnoreEmpty = ini.GetBool("General", "IgnoreEmpty") ?? false;
Settings.AfterExtractHookContent = ini.GetString("Hooks", "AfterExtract");
Settings.BeforePublishHookContent = ini.GetString("Hooks", "BeforePublish");
_onLoadIni();
}
public void RefreshActiveSession()
{
_activeSession?.Dispose();
_activeSession = new Model.ActiveSession(_session, _settings);
}
internal void SaveSession(Stream st, bool saveGlobalSettings, bool saveSessionSettings)
{
Func<bool, string> iniBool = b => b ? "true" : "false";
var sb = new StringBuilder();
sb.Append("ActionType=").AppendLine(Session.Action == Model.ActionType.Extract ? "Extract" : "Publish");
sb.Append("FolderPath=\"").Append(Session.FolderPath).AppendLine("\"");
sb.Append("FilePath=\"").Append(Session.FilePath).AppendLine("\"");
if (saveSessionSettings)
{
sb.Append("AddNewDocumentsToFile=").AppendLine(Settings.AddNewDocumentsToFile ? "true" : "false");
sb.Append("IgnoreEmpty=").AppendLine(Settings.IgnoreEmpty ? "true" : "false");
sb.Append("SearchRepositorySubdirectories=").AppendLine(Settings.SearchRepositorySubdirectories ? "true" : "false");
}
if (saveGlobalSettings)
{
sb.Append("Language=\"").Append(Settings.Language).AppendLine("\"");
sb.AppendLine("");
sb.AppendLine("[DiffTool]");
sb.Append("Path =\"").Append(Settings.DiffTool).AppendLine("\"");
sb.Append("Parameters=\"").Append(Settings.DiffToolParameters).AppendLine("\"");
}
if (saveGlobalSettings
&& (!string.IsNullOrEmpty(Settings.AfterExtractHookContent)
|| !string.IsNullOrEmpty(Settings.BeforePublishHookContent)))
{
sb.AppendLine("");
sb.AppendLine("[Hooks]");
if (!string.IsNullOrEmpty(Settings.AfterExtractHookContent))
{
sb.Append("AfterExtract=\"").Append(Settings.AfterExtractHookContent).AppendLine("\"");
}
if (!string.IsNullOrEmpty(Settings.BeforePublishHookContent))
{
sb.Append("BeforePublish=\"").Append(Settings.BeforePublishHookContent).AppendLine("\"");
}
}
if (saveGlobalSettings && RecentFiles.Count > 0)
{
sb.AppendLine("");
sb.AppendLine("[RecentFiles]");
var i = 0;
while (RecentFiles.Count > i)
{
sb.Append((i + 1).ToString(CultureInfo.InvariantCulture))
.Append("=\"").Append(RecentFiles[i]).AppendLine("\"");
++i;
}
}
var buf = Encoding.UTF8.GetBytes(sb.ToString());
st.Write(buf, 0, buf.Length);
}
private void BrowseForSession()
{
try
{
var dlg = new VistaOpenFileDialog
{
Filter = $"{VBASyncResources.MWOpenAllFiles}|*.*|"
+ $"{VBASyncResources.MWOpenSession}|*.ini",
FilterIndex = 2
};
if (dlg.ShowDialog() == true)
{
LoadIni(new Model.AppIniFile(dlg.FileName));
AddRecentFile(dlg.FileName);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, VBASyncResources.MWTitle, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private bool LastSessionExists() => File.Exists(_lastSessionPath);
private void LoadLastSession()
{
try
{
LoadIni(new Model.AppIniFile(_lastSessionPath));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, VBASyncResources.MWTitle, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void LoadRecent(string index)
{
try
{
var exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var i = int.Parse(index) - 1;
try
{
var path = RecentFiles[i];
if (!Path.IsPathRooted(path))
{
path = Path.Combine(exeDir, path);
}
if (!File.Exists(path))
{
throw new FileNotFoundException();
}
LoadIni(new Model.AppIniFile(path));
AddRecentFile(path);
}
catch
{
if (i < RecentFiles.Count)
{
RecentFiles.RemoveAt(i);
}
throw;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, VBASyncResources.MWTitle, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void SaveSession()
{
try
{
var dlg = new VistaSaveFileDialog
{
Filter = $"{VBASyncResources.MWOpenAllFiles}|*.*|"
+ $"{VBASyncResources.MWOpenSession}|*.ini",
FilterIndex = 2
};
if (dlg.ShowDialog() == true)
{
var path = dlg.FileName;
if (!Path.HasExtension(path))
{
path += ".ini";
}
using (var fs = new FileStream(path, FileMode.Create))
{
SaveSession(fs, false, true);
}
AddRecentFile(path);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, VBASyncResources.MWTitle, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}