S7Explorer/ViewModels/MainViewModel.cs

308 lines
9.8 KiB
C#

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Ookii.Dialogs.Wpf;
using S7Explorer.Helpers;
using S7Explorer.Models;
using S7Explorer.Services;
using S7Explorer.Services;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
namespace S7Explorer.ViewModels
{
public partial class MainViewModel : ViewModelBase
{
private readonly ProjectService _projectService;
private readonly ExportService _exportService;
private readonly SearchHelper _searchHelper;
[ObservableProperty]
private ProjectStructure? _projectStructure;
[ObservableProperty]
private ProjectItem? _selectedItem;
[ObservableProperty]
private object? _selectedItemDetails;
[ObservableProperty]
private string _projectPath = string.Empty;
[ObservableProperty]
private bool _isProjectLoaded;
[ObservableProperty]
private string _searchText = string.Empty;
[ObservableProperty]
private bool _isCaseSensitive;
[ObservableProperty]
private bool _useRegex;
[ObservableProperty]
private ObservableCollection<LogEntry> _logEntries = new();
[ObservableProperty]
private ExportSettings _exportSettings = new();
[ObservableProperty]
private bool _isLoading;
public MainViewModel()
{
_projectService = new ProjectService();
_exportService = new ExportService();
_searchHelper = new SearchHelper();
// Initialize log entries collection
LogEntries = LogService.Instance.Logs;
// Initialize export settings
ExportSettings.ExportPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"S7Documentation.txt");
}
partial void OnSelectedItemChanged(ProjectItem? value)
{
SelectedItemDetails = value?.GetDetailsObject();
}
[RelayCommand]
private async Task LoadProject()
{
try
{
var dialog = new VistaOpenFileDialog
{
Title = "Open Siemens S7 Project",
Filter = "S7 Projects (*.s7p)|*.s7p|All files (*.*)|*.*",
CheckFileExists = true
};
if (dialog.ShowDialog() == true)
{
ProjectPath = dialog.FileName;
await LoadProjectFromPath(ProjectPath);
}
}
catch (Exception ex)
{
_logService.LogError(ex);
MessageBox.Show($"Error loading project: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
[RelayCommand]
private async Task ReloadProject()
{
if (string.IsNullOrEmpty(ProjectPath) || !File.Exists(ProjectPath))
{
_logService.LogWarning("No project loaded to reload");
return;
}
await LoadProjectFromPath(ProjectPath);
}
private async Task LoadProjectFromPath(string path)
{
try
{
IsLoading = true;
// Load the project
_logService.LogInfo($"Loading project from {path}");
ProjectStructure = await _projectService.LoadProjectAsync(path);
if (ProjectStructure != null)
{
IsProjectLoaded = true;
_logService.LogInfo("Project loaded successfully");
}
else
{
IsProjectLoaded = false;
_logService.LogError("Failed to load project");
MessageBox.Show("Failed to load project", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
_logService.LogError(ex);
MessageBox.Show($"Error loading project: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
IsLoading = false;
}
}
[RelayCommand]
private void Search()
{
if (!IsProjectLoaded || ProjectStructure == null)
{
_logService.LogWarning("No project loaded to search");
return;
}
if (string.IsNullOrWhiteSpace(SearchText))
{
_logService.LogWarning("No search text specified");
return;
}
try
{
var results = _searchHelper.Search(ProjectStructure, SearchText, IsCaseSensitive, UseRegex);
if (results.Count == 0)
{
_logService.LogInfo($"No results found for '{SearchText}'");
MessageBox.Show($"No results found for '{SearchText}'", "Search Results", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
// Show search results dialog
ShowSearchResults(results);
}
catch (Exception ex)
{
_logService.LogError(ex);
MessageBox.Show($"Error during search: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void ShowSearchResults(List<SearchResult> results)
{
// In a full implementation, this would show a dialog or window with search results
// For demonstration, we'll just select the first result and expand to it
if (results.Count > 0)
{
var firstResult = results[0];
TreeViewHelper.ExpandToItem(firstResult.Item);
SelectedItem = firstResult.Item;
_logService.LogInfo($"Found {results.Count} results, highlighted first result");
MessageBox.Show($"Found {results.Count} results", "Search Results", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
[RelayCommand]
private async Task ExportDocumentation()
{
if (!IsProjectLoaded || ProjectStructure == null)
{
_logService.LogWarning("No project loaded to export");
return;
}
try
{
// Show export settings dialog
bool proceed = ShowExportSettings();
if (!proceed)
return;
IsLoading = true;
// Export the documentation
bool success = await _exportService.ExportProjectAsync(ProjectStructure, ExportSettings);
if (success)
{
_logService.LogInfo($"Documentation exported to {ExportSettings.ExportPath}");
MessageBox.Show($"Documentation exported to {ExportSettings.ExportPath}", "Export Complete", MessageBoxButton.OK, MessageBoxImage.Information);
}
else
{
_logService.LogError("Failed to export documentation");
MessageBox.Show("Failed to export documentation", "Export Failed", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
_logService.LogError(ex);
MessageBox.Show($"Error exporting documentation: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
IsLoading = false;
}
}
private bool ShowExportSettings()
{
// Show file save dialog for export path
var dialog = new VistaSaveFileDialog
{
Title = "Export Documentation",
Filter = GetExportFilter(),
FileName = Path.GetFileName(ExportSettings.ExportPath),
InitialDirectory = Path.GetDirectoryName(ExportSettings.ExportPath)
};
if (dialog.ShowDialog() == true)
{
ExportSettings.ExportPath = dialog.FileName;
// Determine export format from file extension
string extension = Path.GetExtension(dialog.FileName).ToLower();
ExportSettings.ExportFormat = extension switch
{
".md" => ExportFormat.MarkDown,
".html" => ExportFormat.HTML,
".json" => ExportFormat.JSON,
_ => ExportFormat.PlainText
};
return true;
}
return false;
}
private string GetExportFilter()
{
return "Text Files (*.txt)|*.txt|" +
"Markdown Files (*.md)|*.md|" +
"HTML Files (*.html)|*.html|" +
"JSON Files (*.json)|*.json|" +
"All Files (*.*)|*.*";
}
[RelayCommand]
private void ExpandAll()
{
if (ProjectStructure != null)
{
TreeViewHelper.ExpandAll(ProjectStructure);
_logService.LogInfo("Expanded all tree nodes");
}
}
[RelayCommand]
private void CollapseAll()
{
if (ProjectStructure != null)
{
TreeViewHelper.CollapseAll(ProjectStructure);
_logService.LogInfo("Collapsed all tree nodes");
}
}
[RelayCommand]
private void ClearLog()
{
LogEntries.Clear();
_logService.LogInfo("Log cleared");
}
}
}