From 03da58277e6f26ccbcfda9f877a05ad25cbd62b0 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Tue, 3 Mar 2026 09:28:03 +0900 Subject: [PATCH] Allow changing output directory Closes #5 --- src/Models/Settings.cs | 26 +++++++++++ src/ViewModels/MainViewModel.cs | 18 ++++++-- src/ViewModels/SettingsViewModel.cs | 71 ++++++++++++++++++++++++++--- src/Views/SettingsView.axaml | 17 ++++++- src/Views/SettingsView.axaml.cs | 11 ++--- 5 files changed, 124 insertions(+), 19 deletions(-) diff --git a/src/Models/Settings.cs b/src/Models/Settings.cs index f080a24..77786f7 100644 --- a/src/Models/Settings.cs +++ b/src/Models/Settings.cs @@ -13,11 +13,23 @@ class Settings : ChangeNotifier { private string _lastUsedPath; private bool _useDocnetPDFImageRendering; + private bool _saveOutputPdfInWorkingDir; + private string _outputPdfDir; public Settings() { _lastUsedPath = ""; _useDocnetPDFImageRendering = true; + _saveOutputPdfInWorkingDir = true; + _outputPdfDir = ""; + } + + public Settings(Settings other) + { + _lastUsedPath = other.LastUsedPath; + _useDocnetPDFImageRendering = other.UseDocnetPDFImageRendering; + _saveOutputPdfInWorkingDir = other.SaveOutputPdfInWorkingDir; + _outputPdfDir = other.OutputPdfDir; } [JsonInclude] @@ -35,6 +47,20 @@ class Settings : ChangeNotifier set { _useDocnetPDFImageRendering = value; NotifyPropertyChanged(); } } + [JsonInclude] + public bool SaveOutputPdfInWorkingDir + { + get => _saveOutputPdfInWorkingDir; + set { _saveOutputPdfInWorkingDir = value; NotifyPropertyChanged(); } + } + + [JsonInclude] + public string OutputPdfDir + { + get => _outputPdfDir; + set { _outputPdfDir = value; NotifyPropertyChanged(); } + } + public static string GetSettingsFileName() { return "settings.json"; diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index 3ff98d8..9ef78d4 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -256,7 +256,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown public async Task ShowSettings() { - var updatedSettings = await DialogHost.Show(new SettingsViewModel(_settings)); + var updatedSettings = await DialogHost.Show(new SettingsViewModel(_settings, TopLevelGrabber)); if (updatedSettings != null) { _settings = (Settings)updatedSettings; @@ -575,6 +575,14 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown { // TODO: calculate needed width for images based on page width and margins and all that? // TODO: resize (non-HEIC) images for smaller size...? + // safety checks + var outputDir = _settings.SaveOutputPdfInWorkingDir ? folderPath : _settings.OutputPdfDir; + if (!Directory.Exists(outputDir)) + { + await DialogHost.Show(new WarningViewModel("Output directory not found! Please adjust your application Settings before continuing. Output directory: " + outputDir)); + return; + } + // start making PDF! IsCreatingPDF = true; var pdfDoc = new Document(); var outputFileName = ReportTitle + ".pdf"; @@ -828,15 +836,15 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown }; LogInfo("Rendering document to PDF file..."); pdfRenderer.RenderDocument(); - string outputPDFFileName = Path.Join(folderPath, outputFileName); + string outputPDFFilePath = Path.Join(outputDir, outputFileName); LogInfo("Saving PDF document to disk..."); - pdfRenderer.PdfDocument.Save(outputPDFFileName); - LogInfo("Finished saving PDF output to: " + outputPDFFileName); + pdfRenderer.PdfDocument.Save(outputPDFFilePath); + LogInfo("Finished saving PDF output to: " + outputPDFFilePath); await CreateAndSaveReportObjectAfterReportCreation(); // clean up data dir Directory.Delete(convertedDir, true); // show output folder to user - OpenFolderForFileInFileViewer(outputPDFFileName); + OpenFolderForFileInFileViewer(outputPDFFilePath); IsCreatingPDF = false; } diff --git a/src/ViewModels/SettingsViewModel.cs b/src/ViewModels/SettingsViewModel.cs index b4d7881..0af2265 100644 --- a/src/ViewModels/SettingsViewModel.cs +++ b/src/ViewModels/SettingsViewModel.cs @@ -25,15 +25,15 @@ class SettingsViewModel: ChangeNotifier { private Settings _previousSettings; private Settings _settings; + private string _errorMessage; + private ITopLevelGrabber? _topLevelGrabber; - public SettingsViewModel(Settings settingsToEdit) + public SettingsViewModel(Settings settingsToEdit, ITopLevelGrabber? topLevelGrabber) { _previousSettings = settingsToEdit; - _settings = new Settings - { - LastUsedPath = _previousSettings.LastUsedPath, - UseDocnetPDFImageRendering = _previousSettings.UseDocnetPDFImageRendering - }; + _settings = new Settings(settingsToEdit); // clone it + _errorMessage = ""; + _topLevelGrabber = topLevelGrabber; } public bool UseDocnetPDFImageRendering @@ -46,6 +46,65 @@ class SettingsViewModel: ChangeNotifier } } + public bool SaveOutputPdfInWorkingDir + { + get => _settings.SaveOutputPdfInWorkingDir; + set + { + _settings.SaveOutputPdfInWorkingDir = value; + NotifyPropertyChanged(); + } + } + + public string OutputPdfDirPath + { + get => _settings.OutputPdfDir; + set + { + _settings.OutputPdfDir = value; + NotifyPropertyChanged(); + } + } + + public bool IsOutputPdfDirValid + { + get => SaveOutputPdfInWorkingDir || (!SaveOutputPdfInWorkingDir && Directory.Exists(OutputPdfDirPath)); + } + + public bool HasErrorMessage + { + get => !string.IsNullOrWhiteSpace(_errorMessage); + } + + public string ErrorMessage + { + get => _errorMessage; + set + { + _errorMessage = value; + NotifyPropertyChanged(); + NotifyPropertyChanged(nameof(HasErrorMessage)); + } + } + + public async void ChooseOutputFolder() + { + var topLevel = _topLevelGrabber?.GetTopLevel(); + if (topLevel != null) + { + var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions() + { + Title = "Choose where to save your report file...", + AllowMultiple = false, + }); + if (folders.Count == 1) + { + var folder = folders[0]; + OutputPdfDirPath = folder.Path.LocalPath; + } + } + } + public void Cancel() { DialogHost.Close("DialogHost", null); diff --git a/src/Views/SettingsView.axaml b/src/Views/SettingsView.axaml index ce286b8..3cac9bc 100644 --- a/src/Views/SettingsView.axaml +++ b/src/Views/SettingsView.axaml @@ -12,13 +12,26 @@ MaxWidth="350"> + Spacing="8" + Margin="12,4,12,4">