308 lines
9.8 KiB
C#
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");
|
|
}
|
|
}
|
|
} |