From fb7f2b7fa4ac7614b66edd5179089fdde6e0353a Mon Sep 17 00:00:00 2001 From: Andy Jordan Date: Tue, 23 Aug 2022 11:06:45 -0700 Subject: [PATCH 1/4] Deprecate `GraphicalTools` and `OutGridView.Gui` modules --- GraphicalTools.build.ps1 | 4 +- .../AvaloniaProcessBridge.cs | 101 ------ ...Microsoft.PowerShell.GraphicalTools.csproj | 19 - .../Microsoft.PowerShell.GraphicalTools.psd1 | 140 -------- .../Microsoft.PowerShell.GraphicalTools.psm1 | 10 - .../ModuleLayout.psd1 | 19 - .../OutGridviewCmdletCommand.cs | 176 --------- .../TypeGetter.cs | 199 ----------- src/OutGridView.Gui/.gitignore | 337 ------------------ src/OutGridView.Gui/App.xaml | 13 - src/OutGridView.Gui/App.xaml.cs | 15 - .../Assets/Powershell_black.ico | Bin 127271 -> 0 bytes src/OutGridView.Gui/AvaloniaAppRunner.cs | 81 ----- .../Converters/EnumToDescriptionConverter.cs | 24 -- .../Converters/IValueToStringConverter.cs | 25 -- src/OutGridView.Gui/FodyWeavers.xml | 3 - src/OutGridView.Gui/FodyWeavers.xsd | 26 -- src/OutGridView.Gui/Models/Column.cs | 24 -- src/OutGridView.Gui/Models/Filter.cs | 35 -- src/OutGridView.Gui/Models/FilterGroup.cs | 27 -- src/OutGridView.Gui/Models/NumericFilter.cs | 11 - .../Models/NumericFilterOperator.cs | 12 - .../Models/StringFilterOperator.cs | 27 -- src/OutGridView.Gui/OutGridView.Gui.csproj | 32 -- src/OutGridView.Gui/Program.cs | 38 -- .../Services/EnumExtensions.cs | 23 -- src/OutGridView.Gui/Services/FilterBuilder.cs | 96 ----- .../FilterOperators/ContainsOperator.cs | 23 -- .../FilterOperators/EndsWithOperator.cs | 21 -- .../FilterOperators/EqualsOperator.cs | 22 -- .../FilterOperators/FilterOperatorLookup.cs | 36 -- .../FilterOperators/IFilterOperator.cs | 12 - .../FilterOperators/IStringFilterOperator.cs | 10 - .../FilterOperators/IsEmptyOperator.cs | 20 -- .../FilterOperators/NotContainsOperators.cs | 20 -- .../FilterOperators/NotEqualsOperator.cs | 20 -- .../FilterOperators/NotIsEmptyOperator.cs | 20 -- .../FilterOperators/NumericFilterOperator.cs | 13 - .../FilterOperators/StartsWithOperator.cs | 21 -- src/OutGridView.Gui/Services/ModalService.cs | 22 -- .../Services/PowerShellCodeGenerator.cs | 41 --- src/OutGridView.Gui/Style.xaml | 58 --- src/OutGridView.Gui/ViewLocator.cs | 38 -- .../ViewModels/DataGridViewModel.cs | 72 ---- .../ViewModels/FilterQueryBuilderViewModel.cs | 129 ------- .../ViewModels/MainWindowViewModel.cs | 86 ----- .../ViewModels/ShowCodeModalViewModel.cs | 47 --- .../ViewModels/ViewModelBase.cs | 22 -- src/OutGridView.Gui/Views/DataGridView.xaml | 26 -- .../Views/DataGridView.xaml.cs | 75 ---- .../Views/FilterQueryBuilderView.xaml | 53 --- .../Views/FilterQueryBuilderView.xaml.cs | 36 -- src/OutGridView.Gui/Views/MainWindow.xaml | 80 ----- src/OutGridView.Gui/Views/MainWindow.xaml.cs | 29 -- .../Views/ShowCodeModalView.xaml | 11 - .../Views/ShowCodeModalView.xaml.cs | 29 -- 56 files changed, 1 insertion(+), 2608 deletions(-) delete mode 100644 src/Microsoft.PowerShell.GraphicalTools/AvaloniaProcessBridge.cs delete mode 100644 src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.csproj delete mode 100644 src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.psd1 delete mode 100644 src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.psm1 delete mode 100644 src/Microsoft.PowerShell.GraphicalTools/ModuleLayout.psd1 delete mode 100644 src/Microsoft.PowerShell.GraphicalTools/OutGridviewCmdletCommand.cs delete mode 100644 src/Microsoft.PowerShell.GraphicalTools/TypeGetter.cs delete mode 100644 src/OutGridView.Gui/.gitignore delete mode 100644 src/OutGridView.Gui/App.xaml delete mode 100644 src/OutGridView.Gui/App.xaml.cs delete mode 100644 src/OutGridView.Gui/Assets/Powershell_black.ico delete mode 100644 src/OutGridView.Gui/AvaloniaAppRunner.cs delete mode 100644 src/OutGridView.Gui/Converters/EnumToDescriptionConverter.cs delete mode 100644 src/OutGridView.Gui/Converters/IValueToStringConverter.cs delete mode 100644 src/OutGridView.Gui/FodyWeavers.xml delete mode 100644 src/OutGridView.Gui/FodyWeavers.xsd delete mode 100644 src/OutGridView.Gui/Models/Column.cs delete mode 100644 src/OutGridView.Gui/Models/Filter.cs delete mode 100644 src/OutGridView.Gui/Models/FilterGroup.cs delete mode 100644 src/OutGridView.Gui/Models/NumericFilter.cs delete mode 100644 src/OutGridView.Gui/Models/NumericFilterOperator.cs delete mode 100644 src/OutGridView.Gui/Models/StringFilterOperator.cs delete mode 100644 src/OutGridView.Gui/OutGridView.Gui.csproj delete mode 100644 src/OutGridView.Gui/Program.cs delete mode 100644 src/OutGridView.Gui/Services/EnumExtensions.cs delete mode 100644 src/OutGridView.Gui/Services/FilterBuilder.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/ContainsOperator.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/EndsWithOperator.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/EqualsOperator.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/FilterOperatorLookup.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/IFilterOperator.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/IStringFilterOperator.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/IsEmptyOperator.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/NotContainsOperators.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/NotEqualsOperator.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/NotIsEmptyOperator.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/NumericFilterOperator.cs delete mode 100644 src/OutGridView.Gui/Services/FilterOperators/StartsWithOperator.cs delete mode 100644 src/OutGridView.Gui/Services/ModalService.cs delete mode 100644 src/OutGridView.Gui/Services/PowerShellCodeGenerator.cs delete mode 100644 src/OutGridView.Gui/Style.xaml delete mode 100644 src/OutGridView.Gui/ViewLocator.cs delete mode 100644 src/OutGridView.Gui/ViewModels/DataGridViewModel.cs delete mode 100644 src/OutGridView.Gui/ViewModels/FilterQueryBuilderViewModel.cs delete mode 100644 src/OutGridView.Gui/ViewModels/MainWindowViewModel.cs delete mode 100644 src/OutGridView.Gui/ViewModels/ShowCodeModalViewModel.cs delete mode 100644 src/OutGridView.Gui/ViewModels/ViewModelBase.cs delete mode 100644 src/OutGridView.Gui/Views/DataGridView.xaml delete mode 100644 src/OutGridView.Gui/Views/DataGridView.xaml.cs delete mode 100644 src/OutGridView.Gui/Views/FilterQueryBuilderView.xaml delete mode 100644 src/OutGridView.Gui/Views/FilterQueryBuilderView.xaml.cs delete mode 100644 src/OutGridView.Gui/Views/MainWindow.xaml delete mode 100644 src/OutGridView.Gui/Views/MainWindow.xaml.cs delete mode 100644 src/OutGridView.Gui/Views/ShowCodeModalView.xaml delete mode 100644 src/OutGridView.Gui/Views/ShowCodeModalView.xaml.cs diff --git a/GraphicalTools.build.ps1 b/GraphicalTools.build.ps1 index ce56bc1..152da87 100644 --- a/GraphicalTools.build.ps1 +++ b/GraphicalTools.build.ps1 @@ -3,9 +3,7 @@ param( [ValidateSet("Debug", "Release")] [string]$Configuration = "Debug", - [string[]]$ModuleName = @( - #"Microsoft.PowerShell.GraphicalTools", - "Microsoft.PowerShell.ConsoleGuiTools" ) + [string[]]$ModuleName = @("Microsoft.PowerShell.ConsoleGuiTools" ) ) $script:IsUnix = $PSVersionTable.PSEdition -and $PSVersionTable.PSEdition -eq "Core" -and !$IsWindows diff --git a/src/Microsoft.PowerShell.GraphicalTools/AvaloniaProcessBridge.cs b/src/Microsoft.PowerShell.GraphicalTools/AvaloniaProcessBridge.cs deleted file mode 100644 index 59a6536..0000000 --- a/src/Microsoft.PowerShell.GraphicalTools/AvaloniaProcessBridge.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Management.Automation; -using System.Reflection; -using System.Runtime.InteropServices; -using OutGridView.Models; - -namespace OutGridView.Cmdlet -{ - class AvaloniaProcessBridge - { - private static Process _process; - - public static List SelectedIndexes { get; set; } - public static void Start(ApplicationData applicationData) - { - SelectedIndexes = new List(); - - _process = new Process(); - _process.StartInfo.FileName = GetOutgridViewApplicationLocation(); - - - _process.StartInfo.CreateNoWindow = true; - _process.StartInfo.UseShellExecute = false; - - _process.StartInfo.RedirectStandardInput = true; - _process.StartInfo.RedirectStandardOutput = true; - _process.StartInfo.RedirectStandardError = true; - - _process.OutputDataReceived += (sender, data) => - { - if (!string.IsNullOrWhiteSpace(data.Data)) - { - SelectedIndexes = Serializers.ObjectFromJson>(data.Data); - } - }; - - _process.ErrorDataReceived += (sender, data) => - { - Console.WriteLine(data.Data); - }; - - _process.Start(); - _process.BeginOutputReadLine(); - _process.BeginErrorReadLine(); - - var serializedData = Serializers.ObjectToJson(applicationData); - - _process.StandardInput.WriteLine(serializedData); - - } - public static void WaitForExit() - { - _process.WaitForExit(); - } - - public static void CloseProcess() - { - _process.Close(); - } - public static bool IsClosed() - { - if (_process == null || _process.HasExited) - { - return true; - } - else - { - return false; - } - } - - public static string GetOutgridViewApplicationLocation() - { - string osRid; - string executableName; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - osRid = "win-x64"; - executableName = "OutGridView.Gui.exe"; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - osRid = "osx-x64"; - executableName = "OutGridView.Gui"; - } - else - { - osRid = "linux-x64"; - executableName = "OutGridView.Gui"; - } - - return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "OutGridView.Gui", osRid, executableName); - } - } -} diff --git a/src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.csproj b/src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.csproj deleted file mode 100644 index c19b837..0000000 --- a/src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net6.0 - - - - - - - - - - - - - - - diff --git a/src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.psd1 b/src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.psd1 deleted file mode 100644 index 30e1e27..0000000 --- a/src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.psd1 +++ /dev/null @@ -1,140 +0,0 @@ -# -# Copyright (c) Microsoft. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -@{ - -# Script module or binary module file associated with this manifest. -RootModule = 'Microsoft.PowerShell.GraphicalTools.psm1' - -# Version number of this module. -ModuleVersion = '0.2.0' - -# Supported PSEditions -CompatiblePSEditions = @( 'Core' ) - -# ID used to uniquely identify this module -GUID = '06028f35-8304-4460-ae73-306741982afe' - -# Author of this module -Author = 'PowerShell Team' - -# Company or vendor of this module -CompanyName = 'Microsoft' - -# Copyright statement for this module -Copyright = '(c) Microsoft Corporation. All rights reserved.' - -# Description of the functionality provided by this module -Description = 'Cross-platform GUI Tools for PowerShell' - -# Minimum version of the PowerShell engine required by this module -PowerShellVersion = '6.2' - -# Name of the PowerShell host required by this module -# PowerShellHostName = '' - -# Minimum version of the PowerShell host required by this module -# PowerShellHostVersion = '' - -# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# DotNetFrameworkVersion = '' - -# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# CLRVersion = '' - -# Processor architecture (None, X86, Amd64) required by this module -# ProcessorArchitecture = '' - -# Modules that must be imported into the global environment prior to importing this module -# RequiredModules = @() - -# Assemblies that must be loaded prior to importing this module -# RequiredAssemblies = @() - -# Script files (.ps1) that are run in the caller's environment prior to importing this module. -# ScriptsToProcess = @() - -# Type files (.ps1xml) to be loaded when importing this module -# TypesToProcess = @() - -# Format files (.ps1xml) to be loaded when importing this module -# FormatsToProcess = @() - -# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -NestedModules = @( 'Microsoft.PowerShell.GraphicalTools.dll' ) - -# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = @() - -# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. -CmdletsToExport = @( 'Out-GridView' ) - -# Variables to export from this module -VariablesToExport = '*' - -# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. -AliasesToExport = @( 'ogv' ) - -# DSC resources to export from this module -# DscResourcesToExport = @() - -# List of all modules packaged with this module -# ModuleList = @() - -# List of all files packaged with this module -# FileList = @() - -# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. -PrivateData = @{ - - PSData = @{ - - # Tags applied to this module. These help with module discovery in online galleries. - Tags = @('Gui', 'Out-GridView', 'MacOS', 'Windows', 'Linux', 'Avalonia', 'PSEdition_Core') - - # A URL to the license for this module. - LicenseUri = 'https://github.com/PowerShell/GraphicalTools/blob/master/LICENSE.txt' - - # A URL to the main website for this project. - ProjectUri = 'https://github.com/PowerShell/GraphicalTools/' - - # A URL to an icon representing this module. - # IconUri = '' - - # ReleaseNotes of this module - ReleaseNotes = '# 0.2.0 -Adds support for primitives -Adds support for mixed-object arrays (e.g Get-ChildItem) -Improves window sizing - -# 0.1.1 - -Fix for non-Windows - -# v0.1.0 - -Initial Release -' - - # Prerelease string of this module - # Prerelease = '' - - # Flag to indicate whether the module requires explicit user acceptance for install/update/save - RequireLicenseAcceptance = $false - - # External dependent modules of this module - # ExternalModuleDependencies = @() - - } # End of PSData hashtable - -} # End of PrivateData hashtable - -# HelpInfo URI of this module -# HelpInfoURI = '' - -# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. -# DefaultCommandPrefix = '' - -} diff --git a/src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.psm1 b/src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.psm1 deleted file mode 100644 index ef6f736..0000000 --- a/src/Microsoft.PowerShell.GraphicalTools/Microsoft.PowerShell.GraphicalTools.psm1 +++ /dev/null @@ -1,10 +0,0 @@ -# -# Copyright (c) Microsoft. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -if($IsMacOS) { - chmod +x "$PSScriptRoot/OutGridView.Gui/osx-x64/OutGridView.Gui" -} elseif ($IsLinux) { - chmod +x "$PSScriptRoot/OutGridView.Gui/linux-x64/OutGridView.Gui" -} diff --git a/src/Microsoft.PowerShell.GraphicalTools/ModuleLayout.psd1 b/src/Microsoft.PowerShell.GraphicalTools/ModuleLayout.psd1 deleted file mode 100644 index dddfb29..0000000 --- a/src/Microsoft.PowerShell.GraphicalTools/ModuleLayout.psd1 +++ /dev/null @@ -1,19 +0,0 @@ -@{ - RequiredBuildAssets = @{ - 'Microsoft.PowerShell.GraphicalTools' = @( - "publish/Microsoft.PowerShell.GraphicalTools.dll", - "publish/Microsoft.PowerShell.GraphicalTools.pdb", - "publish/Microsoft.PowerShell.GraphicalTools.psd1", - "publish/Microsoft.PowerShell.GraphicalTools.psm1" - ) - - 'Microsoft.PowerShell.OutGridView.Models' = @( - 'publish/Microsoft.PowerShell.OutGridView.Models.dll', - 'publish/Microsoft.PowerShell.OutGridView.Models.pdb' - ) - } - - NativeBuildAssets = @{ - 'OutGridView.Gui' = @("win-x64", "osx-x64", "linux-x64") - } -} diff --git a/src/Microsoft.PowerShell.GraphicalTools/OutGridviewCmdletCommand.cs b/src/Microsoft.PowerShell.GraphicalTools/OutGridviewCmdletCommand.cs deleted file mode 100644 index 08dba42..0000000 --- a/src/Microsoft.PowerShell.GraphicalTools/OutGridviewCmdletCommand.cs +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Management.Automation; -using System.Management.Automation.Internal; -using OutGridView.Models; -using System.Linq; - -namespace OutGridView.Cmdlet -{ - /// Enum for SelectionMode parameter. - /// - [Cmdlet(VerbsData.Out, "GridView", DefaultParameterSetName = "PassThru")] - [Alias("ogv")] - public class OutGridViewCmdletCommand : PSCmdlet - { - #region Properties - - private const string DataNotQualifiedForGridView = "DataNotQualifiedForGridView"; - - private List PSObjects = new List(); - - #endregion Properties - - #region Input Parameters - - /// - /// This parameter specifies the current pipeline object. - /// - [Parameter(ValueFromPipeline = true)] - public PSObject InputObject { get; set; } = AutomationNull.Value; - - /// - /// Gets/sets the title of the Out-GridView window. - /// - [Parameter] - [ValidateNotNullOrEmpty] - public string Title { get; set; } - - /// - /// Get or sets a value indicating whether the cmdlet should wait for the window to be closed. - /// - [Parameter(ParameterSetName = "Wait")] - public SwitchParameter Wait { get; set; } - - /// - /// Get or sets a value indicating whether the selected items should be written to the pipeline - /// and if it should be possible to select multiple or single list items. - /// - [Parameter(ParameterSetName = "OutputMode")] - public OutputModeOption OutputMode { set; get; } - - /// - /// Gets or sets a value indicating whether the selected items should be written to the pipeline. - /// Setting this to true is the same as setting the OutputMode to Multiple. - /// - [Parameter(ParameterSetName = "PassThru")] - public SwitchParameter PassThru - { - set { this.OutputMode = value.IsPresent ? OutputModeOption.Multiple : OutputModeOption.None; } - - get { return OutputMode == OutputModeOption.Multiple ? new SwitchParameter(true) : new SwitchParameter(false); } - } - - #endregion Input Parameters - - // This method gets called once for each cmdlet in the pipeline when the pipeline starts executing - protected override void BeginProcessing() - { - } - - // This method will be called for each input received from the pipeline to this cmdlet; if no input is received, this method is not called - protected override void ProcessRecord() - { - if (InputObject == null || InputObject == AutomationNull.Value) - { - return; - } - - IDictionary dictionary = InputObject.BaseObject as IDictionary; - if (dictionary != null) - { - // Dictionaries should be enumerated through because the pipeline does not enumerate through them. - foreach (DictionaryEntry entry in dictionary) - { - ProcessObject(PSObject.AsPSObject(entry)); - } - } - else - { - ProcessObject(InputObject); - } - } - - protected override void StopProcessing() - { - if (this.Wait || this.OutputMode != OutputModeOption.None) - { - AvaloniaProcessBridge.CloseProcess(); - } - } - - private void ProcessObject(PSObject input) - { - - object baseObject = input.BaseObject; - - // Throw a terminating error for types that are not supported. - if (baseObject is ScriptBlock || - baseObject is SwitchParameter || - baseObject is PSReference || - baseObject is PSObject) - { - ErrorRecord error = new ErrorRecord( - new FormatException("Invalid data type for Out-GridView"), - DataNotQualifiedForGridView, - ErrorCategory.InvalidType, - null); - - this.ThrowTerminatingError(error); - } - - PSObjects.Add(input); - } - - // This method will be called once at the end of pipeline execution; if no input is received, this method is not called - protected override void EndProcessing() - { - base.EndProcessing(); - - //Return if no objects - if (PSObjects.Count == 0) - { - return; - } - - var TG = new TypeGetter(this); - - var dataTable = TG.CastObjectsToTableView(PSObjects); - var applicationData = new ApplicationData - { - Title = Title, - OutputMode = OutputMode, - PassThru = PassThru, - DataTable = dataTable - }; - - - AvaloniaProcessBridge.Start(applicationData); - - if (this.Wait || this.OutputMode != OutputModeOption.None) - { - AvaloniaProcessBridge.WaitForExit(); - } - - var selectedIndexes = AvaloniaProcessBridge.SelectedIndexes; - - if (selectedIndexes == null) - return; - - foreach (int idx in selectedIndexes) - { - var selectedObject = PSObjects[idx]; - if (selectedObject == null) - { - continue; - } - this.WriteObject(selectedObject, false); - } - } - } -} diff --git a/src/Microsoft.PowerShell.GraphicalTools/TypeGetter.cs b/src/Microsoft.PowerShell.GraphicalTools/TypeGetter.cs deleted file mode 100644 index de5e0b3..0000000 --- a/src/Microsoft.PowerShell.GraphicalTools/TypeGetter.cs +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Management.Automation; -using System.Linq; -using System.Globalization; -using System.Collections.Generic; -using Microsoft.PowerShell.Commands; -using OutGridView.Models; - -namespace OutGridView.Cmdlet -{ - public class TypeGetter - { - private PSCmdlet _cmdlet; - - public TypeGetter(PSCmdlet cmdlet) - { - _cmdlet = cmdlet; - } - public FormatViewDefinition GetFormatViewDefinitionForObject(PSObject obj) - { - var typeName = obj.BaseObject.GetType().FullName; - - var types = _cmdlet.InvokeCommand.InvokeScript(@"Microsoft.PowerShell.Utility\Get-FormatData " + typeName).ToList(); - - //No custom type definitions found - try the PowerShell specific format data - if (types == null || types.Count == 0) - { - types = _cmdlet.InvokeCommand - .InvokeScript(@"Microsoft.PowerShell.Utility\Get-FormatData -PowerShellVersion $PSVersionTable.PSVersion " + typeName).ToList(); - - if (types == null || types.Count == 0) - { - return null; - } - } - - var extendedTypeDefinition = types[0].BaseObject as ExtendedTypeDefinition; - - return extendedTypeDefinition.FormatViewDefinition[0]; - } - - public DataTableRow CastObjectToDataTableRow(PSObject ps, List dataColumns, int objectIndex) - { - Dictionary valuePairs = new Dictionary(); - - foreach (var dataColumn in dataColumns) - { - var expression = new PSPropertyExpression(ScriptBlock.Create(dataColumn.PropertyScriptAccessor)); - - var result = expression.GetValues(ps).FirstOrDefault().Result; - - var stringValue = result?.ToString() ?? String.Empty; - - var isDecimal = decimal.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out var decimalValue); - - if (isDecimal) - { - valuePairs[dataColumn.ToString()] = new DecimalValue { DisplayValue = stringValue, SortValue = decimalValue }; - } - else - { - valuePairs[dataColumn.ToString()] = new StringValue { DisplayValue = stringValue }; - } - } - - return new DataTableRow(valuePairs, objectIndex); - } - - private void SetTypesOnDataColumns(List dataTableRows, List dataTableColumns) - { - var dataRows = dataTableRows.Select(x => x.Values); - - foreach (var dataColumn in dataTableColumns) - { - dataColumn.StringType = typeof(decimal).FullName; - } - - //If every value in a column could be a decimal, assume that it is supposed to be a decimal - foreach (var dataRow in dataRows) - { - foreach (var dataColumn in dataTableColumns) - { - if (!(dataRow[dataColumn.ToString()] is DecimalValue)) - { - dataColumn.StringType = typeof(string).FullName; - } - } - } - } - private List GetDataColumnsForObject(List psObjects) - { - var dataColumns = new List(); - - - - foreach (PSObject obj in psObjects) - { - var labels = new List(); - - FormatViewDefinition fvd = GetFormatViewDefinitionForObject(obj); - - var propertyAccessors = new List(); - - if (fvd == null) - { - if (PSObjectIsPrimitive(obj)) - { - labels = new List { obj.BaseObject.GetType().Name }; - propertyAccessors = new List { "$_" }; - } - else - { - labels = obj.Properties.Select(x => x.Name).ToList(); - propertyAccessors = obj.Properties.Select(x => $"$_.\"{x.Name}\"").ToList(); - } - } - else - { - var tableControl = fvd.Control as TableControl; - - var definedColumnLabels = tableControl.Headers.Select(x => x.Label); - - var displayEntries = tableControl.Rows[0].Columns.Select(x => x.DisplayEntry); - - var propertyLabels = displayEntries.Select(x => x.Value); - - //Use the TypeDefinition Label if availble otherwise just use the property name as a label - labels = definedColumnLabels.Zip(propertyLabels, (definedColumnLabel, propertyLabel) => - { - if (String.IsNullOrEmpty(definedColumnLabel)) - { - return propertyLabel; - } - return definedColumnLabel; - }).ToList(); - - - propertyAccessors = displayEntries.Select(x => - { - //If it's a propety access directly - if (x.ValueType == DisplayEntryValueType.Property) - { - return $"$_.\"{x.Value}\""; - } - //Otherwise return access script - return x.Value; - }).ToList(); - } - - for (var i = 0; i < labels.Count; i++) - { - dataColumns.Add(new DataTableColumn(labels[i], propertyAccessors[i])); - } - } - return dataColumns.Distinct().ToList(); - } - - public DataTable CastObjectsToTableView(List psObjects) - { - List objectFormats = psObjects.Select(GetFormatViewDefinitionForObject).ToList(); - - var dataTableColumns = GetDataColumnsForObject(psObjects); - - foreach (var dataColumn in dataTableColumns) - { - _cmdlet.WriteVerbose(dataColumn.ToString()); - } - - List dataTableRows = new List(); - for (var i = 0; i < objectFormats.Count; i++) - { - var dataTableRow = CastObjectToDataTableRow(psObjects[i], dataTableColumns, i); - dataTableRows.Add(dataTableRow); - } - - SetTypesOnDataColumns(dataTableRows, dataTableColumns); - - return new DataTable(dataTableColumns, dataTableRows); - } - - - //Types that are condisidered primitives to PowerShell but not C# - private readonly static List additionalPrimitiveTypes = new List { "System.String", - "System.Decimal", - "System.IntPtr", - "System.Security.SecureString", - "System.Numerics.BigInteger" - }; - private bool PSObjectIsPrimitive(PSObject ps) - { - var psBaseType = ps.BaseObject.GetType(); - - return psBaseType.IsPrimitive || psBaseType.IsEnum || additionalPrimitiveTypes.Contains(psBaseType.FullName); - } - } -} diff --git a/src/OutGridView.Gui/.gitignore b/src/OutGridView.Gui/.gitignore deleted file mode 100644 index dbe7c8f..0000000 --- a/src/OutGridView.Gui/.gitignore +++ /dev/null @@ -1,337 +0,0 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -## Visual Studio Code specific files and folder -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.jsons - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ -**/Properties/launchSettings.json - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ diff --git a/src/OutGridView.Gui/App.xaml b/src/OutGridView.Gui/App.xaml deleted file mode 100644 index 622d784..0000000 --- a/src/OutGridView.Gui/App.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/src/OutGridView.Gui/App.xaml.cs b/src/OutGridView.Gui/App.xaml.cs deleted file mode 100644 index e9351e3..0000000 --- a/src/OutGridView.Gui/App.xaml.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Avalonia.Markup.Xaml; - -namespace OutGridView.Application -{ - public class App : Avalonia.Application - { - public override void Initialize() - { - AvaloniaXamlLoader.Load(this); - } - } -} diff --git a/src/OutGridView.Gui/Assets/Powershell_black.ico b/src/OutGridView.Gui/Assets/Powershell_black.ico deleted file mode 100644 index 2ef67c76a1f48defeb00b8e3095410ac0c7688fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 127271 zcmeFa2|Sej*FS!ZeU~LWLkmL2nq(P8X%Ur53k@xVY^m%sgODU`ij;GzAuk-32#w_Q&Kj*y9`#6{2qfxs{Z-=1rXF)i-F|i{}Fm;iV@qx z+k>x-To1dpb4MwPw~0HL!ase-R(`FOtGg>tqy&%Op}vvre3D+ad8@vdYUppWxDfnG zm@65x=WzN{r`z!^+b7=Qrk8jga?4t#s#llDFfb`$m^X+lt}GyuhTDopJaWg<`=3xe zBlh7^N?RjFN;|tszkc$5!2jsU|BJU-+jr;o%c>IgbX8mO(GNgc9VAoP169*WLWYg3 z7&uAD@zkm%H$?R3+b|_U^j1pxs?YC+mkk&Xh|p$NeD#D-jO%vG$qlPkZqST=VC{x< z=;d-1^dM5PPuIqY86D<4YA1%i0(u6Wdv!3j?9pgUq!Rt3oe%-~-ik2N0) zk41=AukC4P9eXx2^hIr!w^#htmBHLA*Rn|?1qF5!{Ri&#inhNvcC9C1hhua0wE%V- zWhFZ4SNssXsxA#QJU6V zc}PJ+y;vZQ0T-7A(3#h}D;lyl#C45}MQ+zhcz#ylTvSVVIc2$>8l71&!07KuRIqs1 zf7<)XSc;x!sJPN%|9DS_jL)JRHwe?splxpwHy;wePjp2(OT*%NakgbQ0(`ffE1~5E zn#5A@xaF*5qwxO2tmuMctmwN2x@Y8(qs|6MIB_?f*&XpY;|bfWEdNC9odeY){P33< z4UriKxdChS$O~G`S7Vi=hM>_L9cd&g?Wh7TRiQ(P*lEg#c-@VK<1W3CBf6Bu!U?H0 zWJ=I!ZfgHRe&UN*g3sPimi&Q%j#i5)(r6j+zT%UwIjy^wi)??w=Nh5739}0$#x6NN zgL$cXIABFAWdlhQ_K2+HA>vgQ60_c?@=*Erh_Gf;A0DSS@cHr}?A;=){Ws^;+EL4 zfEZzF$7pr7b!0sYk)nHesbs;1h0aAtCf(#r4Gqr6Mo*z6h~_{-UJhJ1 zNft%PIjrCAL z2f7t%Z2xerN6<38yL_xbf^kJ5$ecBuSjR(LE|&!h?=xamIj%xB=3j%TM@rViwd-t8 zd#~yifAvP1$i5dVLsUR-dq8wC-(x3^iPg4gP*dQ0t?67;r5HZa$`2nIt;rvih%VkY zX;`ss{t8@FF(DzOVre`Ee~~Rom&I?cCS&b{@ds!xdK~Hs#Mb3uHZ?)pxoCZx(1VmfklprmAD37f1dKoJ1ie2@2Y?jWUyeOWy0D_j)@WPvGk*U8H``H%MDwRz z(<(@_|CYtas+ra%Ou%=$g zVqWwcItfIlo}`;}r%hHT30~Khe8=ZL9ousUWmxkHl8mI#%-1to;5=T}^<{Hy(%6H^^7uOsvQvBrhBJyBbQ`Ji#;19$YQB z8hfiZ5q$K}EUAcKTp;UE$_7}tb31E#d@}l9n?qQ|*12wHj& zYQIf|$dO~PlsK{GjS{=C|JvyWg1;C)_0Dlz*=gJKU_KnR%$SS4KofkNC^sRzIG+S@ z{E`^SSAEvsG_?Y!sJzVA2q_x6R2*-)iX~4Tf7epdM5?>)TZVUiB?lEapncU@kwNHz z3fxUBA6h4M_wli&KwfT`f{G_Vs_sv7)%q-(C(4zTk9x6f&Haz?@M@N$eGqn#S-w&;jGY@ZAzCICNwbB6b zVn0@&ed#G*nOoZ`Lj2gcjh-(Rk;&kf%esCn%L6*og+@y1LkL&K*Y{sja-l`Yo@ZV5W$KCoPphA_+RI zWJNzQD*Kc7M1q#~LZXYG;b(<2tK7rIWrMeTg|s3gbs(W=LYJOR_5#+tVShMyuiXCp z8D9hsJVN@sAra9Sf>s6{D@x6JEJeo-8t^6*#U(+7{trzG8gswfYi>iS1o-nLQ(#WbaJZb&c^44^rtJx zVJsb7QcD+GvwGJJ2B%iyD(#{Oa8^ZblAjPM$9{@2rawmFBp2-QI@Y}Jl#i;`I3I1E zAr6sexH5uaGhZWCIr;SBH~5*Y#$zQ(-P%sbUQJ|=o*kpVT(tt1-pl||KLva9^UAB+ zU1hvM9U9Wy*cV;XCH)}!3Dm^r!{N^PBthz#GC>4d95I=6Glswt>7$^_mNym|I5MvE zq*YRQ*Puo`#0TSQwA`3z=v!)UsItLY-nS%0%tu-G(?9g6hY_It^Q-({$&nxIwd+EU zzf`Qq9qEoL*3d$rEv*GD_YZS7K2g-IC_T>As$79vDweNd3C>~j7+#Gd4opw5~#3|aEzb?`wm zK~;E&Rc0@-n-YBB$n(Oh?RA$8_Ie~2IsT$Izn?hG1-isVKKuNRpw)MjQ~X(&*yFhB zqOXsq-lWOye;?lxUE#mw?pl!Lp9ai7UCijeo&!%ZSW_Ylz(}4pL|mX^03YEzam3h3 zx9}a0pu?Rale|_Xl0FdK9`*4(qE*Wt!n?s9+$LN^RL2Yv(Y%9!$a7a*l3ra@kD+1b zmjsqf!?Hn{;tBkC@tr!XUK#6?gq*x(h`Ut8F*q8NT+^Vig^68X#wlx;N6elKqaF~o z&s>uD;EE7luJO~jj0zD+g%|bh%8}q_oDcJ>zIAtejp@_lXSk^kBNb@5Ck}bS!c1K; z#4Y414clC*5iy#;OMSav6dZf6EQ&%H*SYKqdJw}50?{!uCVwjcRbe&$T@L9sEyN7_5NnnZCor{q0&NXt5tm8F(uy&y%yC9nalF`TC-NTJN6ao4NE%du zz)<9A-l% ztk}1N^^BRoMIBwW&@VIT;l4BaN`}v0w?VfeIz{r7$;UUAU`~C)q;OHsfb>#0&R4(M z`mT3-WNq2=TN&#zW($POLs1tw)1wD3R}aT?kz@qsTaLiB)o~D&Z#&3_iQYn_3+l5c zU24Bbb>pD!1P5dw{c(kjw&gi|L?2mM=TN|u`m#ev_q{)WC*Bjh7;c#xrM;Xm zxIKK^yeV$O_$IGRhr{ey?+h`a*na)#7ltKWkZJ?k&v`as=s^Vz8c#eG=x7hB^-aa{ z+^3!qi+RaK)iTas-RLQrLq2T(m zv5`saHxff89A8Tl)%P9MLe!WZj~u21ue~s5@mk5gZI*?`H{QaKpFo-->?8Dbv@uH6 zNxZbK`pO3pv%EU{*b&m(ChJq9i^q1IRKrg6*>A`Y(gJmVS(yZ4zUwjl%3cu(;_dn@ zSo}z4(r73~WQU`B%_r0$`xYmCerS3USRjF1om|g)2I%SzoCI+Uedd5-60US4t?}wK z4TK-;Evt}K590=i9(mnN7jHfzNZOUI4#yoEyJ+5I`!bFnzJ-XdZ78%&QCK@fyL_x_S*%0~nqxRV;^#bcd7WoYL^L6E&Z-w{6{b?8tWzV5YG_W<2v|1L>nTiV<5 zvB6i_1eybJW-ssp{j2f|enUCf4o2n}Z*x7iD1Y2jpZ1zXGxc4LC z9eTw!vjudZ z$9kII1wWy!qmQ;dtPCePsXe=2QoIaVQz8e~w!X8Ul9;?abi85%<>g0NNY#yxj(ecP z+X_8>{=7(v3_f?5LPhS=K{@zd&fS^9#Nq1O_Z~mHv6e7uJ~-NzTRC3iFkUMmopf(0 zhG^EL!IX-qpyNNoH@^l7llcyb(+JS54$KERqNxZkar12Fc|jz+)&2@rDolYwU?oN= zMjA7_;(NTa{Huh+Hl|iI#7VUnM&UoRk(+?jRk=ax_Lfayv-yNAiX_Z}+*|S-aCW{` zLRO|{uY@N}?9$dvox)!^C#Noq+?d$_GP+BuuX7Q+^N7!fvulT# z5cTUiAwhxOfsG#igFEswwH;HGV==A=?<(QLU|*&10XMJKE^TFbqCT$za&>Mk886g5 z3>)g2E<&z8xkzU=RILmz6w^{{!asJ;%73Dx!A-V`5}^_H?7khOqyt5Lf-tKPJCRLM z1h0z+S-nTS=uD+zgN}l!yL(T&^6aG3t;Jg|>1!&w3gP=@xruH>j6B=_)El~!--&B} z^WZN^jC=2{eBMmhxe9#|Yz7TolH-P$gI#Ywym)YE8WolnCVnIjbh}4WmZ7zW^cALR zxu~)yyys6iZ*yI&=ZQ42W~{aK42;*5#I9+o17g93MF=C{Cc{ZBi$)lZw=9~~gLXLD zPn>}22W8&I8$x?c`~r$lg>PpiPDPQHd(b`xYbWwRaH#Oe1HbB}gfe-T!8MAJ$#SV$ zCWjx@2kiW}1JZk_@gU2XStZS;>!~2Fvs2#g;YQg~Wb>tf&+Av?pk^AbW7kY$_zQ{{ zb%B-`vhmR)gOzUi?@f9x-1A+dW?blHu7Zpjh{#X4Jq~v+EIHuF>h-o_zaNWHt!zk+ z7s3G& z-f@5x9X$+(dF&m^KhSiYsX5cdR4RonNaAl zo%L*N3Y4jc)00bY)5Z#m1GLUwf9a=ftQiJ9Bj-Vf$2x;zl*!X@EngHDwYnhKRvn&n zF>?XxlT(6BXNt04tOhafA$=V^YSO;^^=%XHV)i%D2T-h+p`{ZhO>qIeEw>c8@c39s zeqx#EI2AHNUqo^Wt28LA(DFBJF&|0iVee8A#+3&~7Bvn(; zUoQxPR>a`jf<9}48e_<+Vph^9JfxRWug142)=N=C#5V0@TfH$!+5@Ks2Gk_B&h{=C z-Jryp30oI~zZHg0QJ)#8=MF;p6>pt8teaq=|3l7tyf10Vi06-Wy^Fjwd7$cA;Di58GM{ z?*%Hj6tnoOX&TpX&HzVhfEt@R_sIwo)nk{I=Ylqy>TGY#N)A7#OvH_f=I81ZNEFOn zMk}g>Wi)$FbK|AD9U0YKa9!zsB$+wo(0~tc<(wuSZq*S; zr{(&*#DwBhygqb%@AF%i($=5EPkn%hYInDb^+=E`jWEPz zJ@?_T#KG7$Cz*DE`_7?KGIbW>8)tfG4Q~swU|AC2%%U7b@Z#kv$2HQ=2b2b~r}!_p zLD!VYUld>S3sEmG<5ZXcx>FSBqKpo6vr2oGc7;HDpBvveS2Wo-q<{R2$a*J{0J`i$ z19{@8N!!7-9%E&@H?0UGut16p z$I1v&uin*1oD-xg_;e-UNt%DaeDnI5W48@i?IazoI}+;?R|-&BjEgO#OoM? zIEts1G9R^dOL4Qjb9gUF_N~AfyX2nuxG~$!(>9MWHBp3uyCBEZs8?W1T85g9=i0L` zz2PDHG;Gjejz7b`Y2#6Kr~=yj8H{M#b6zTDU<2PGKIE<}hPZn>%Q$fbe40#P9y|fBlDaPI^?1jaPGvb7esb4~m2jMM?uFC=DM<}8#Mx}WSD}VodTJ|^ zlyQoWOn~0Df6(;BsB@Q_O<1bK(eb3sjMmQeYM2})wL_;w@h|*07VR&U<35ppoSv!u z5O+r+#fTwiKJ#*Z<>$u5(4fi;Z}gr%cr}%N=a%}c-is*0;oa8=Rga~@w((;xw}1vf z>ng^zPJX`Opn-J^uhl9RuR3U$Ll)C;m#^|sFY$>I)vvq9b(wWOc_1O{LUf5tq#ZVA z-%OS>z0kEuwWN*#$5|iYqlQLoX7sn5<)*gtt%tQo*06XpzBbg?jc}>%s|x4!Ct?ow ztn-}1DI+?c-%10`YBRl`!UpM7be&FG(Ra_$O&3!BzKdDcFJBS0I=HZfBc#?Vn_X)l@xh#ugtO`G76<_)FZzrS^^(3Q zk^K@P;yRWePb^@+_w$@+pm?e8=nm5^>m6Q7`&^V-NjVj789vIxiVhuWX%NB(;T%$W zQLZiZ{ph4ts5sySH`=9%%N=83;TzqwTpq(X{HP7~9i?`uFtU%`z-F&?CJmWvU4MQ4 z@orYbiJDIbq@qmBaW`Uhuqta`&)F&u=|KBKu7d2P z$w#kpx&PkGH-N--4XD~`g|>j%O}C!z?S6ew1dmM!4p^DNYh3_IYYTcB3Jf(T`J+Og-nz-y)cv?PvRz7YRsOT2JL_NzSTfjU8@J- zMulV`A3v||uh1z$yhleVz7MW7*|y$FD{h0lCTuODk)0+=q{jBaVV?WKCZ7O)nVe5r zNLfYF4I*^Y8eD4S0KyY^sKLvpdr!-aJ2kgdlG<|?}9tf5-Q4FrO(MXpm#Z%&TdXj+-rg`gUo7_MJ}9 zgw`DltHu5@*EL?N&7z{c2Jq|(AHHw2@AQa%9Ca7yE)hYPyI!bb=E`!L8%Ex*cZCm7 zUc=|l-=ww1i{Qmmht|asxOQKO(>?oE@+B~Gp45kZR(Oy73aalV&I#KBZPEo9BEMaTtSp%~K9X`A*u zM8?B}vS`D7v;K`I38TxK=&c>rixAhxbdRHZ5792Adh|sI>+N2v4<$}d_o{k#)rG3q&Y0YtcOUVGFTF$QJtX5+>nCZEP9CQ)?-Vpp1_ z4$B_MOlqIz2a!s4bY~XSM>jx-r$#<>r!dx8`TH(F;j%*_KO7=e0c9@g9zG#tLFKDK z_ZW)zQ~*6rDb@|NPWLW%MFlpPyEv9r3=~f9-BEL7teS_lwi1xMlFPG4*PdZ%52lun zB@Yffey4&Iz_$=xsC&mt6|1F?k;#h7=jp8z>&S!!3yJC>TLHe7i4xVYOHlz<%o4f2 zx~q{pYJIB*Zra{R*)!MfZ67~7rxYj0?d=9nwyLUtaAtzmSy%yq05!N+iiMVaXu)dU z=SYpq)4JeRG_4Zn;=1f?j{+ASol4@Rw!6M~BA>*X`FSP+36}4NB zl$Lm!?dyE148cSvZ=)rr_^E8-)rwpyst%{wPYG%}ZXT%-UWIuHP81ECrVbor!&<8{ z00*Ai%8*^iP3*l6Sgt84kY($n6a(IN`L#vieJ!5THyh?^O2?ks&>G%d6rh@)T@ypW zTHmN_xWtMg$wV9VTp}r#@X;O2cJsFLT7jPC+IsjNO}-LmaQCFB^LExz{U+NG%LVjo z`zcdqPxgU#6KM$sjoB?Px+t;pa8)El7>tZw zz7=q$!bhD0KE|v+{oazPuoFKU)_)SyaXk%;AirMkoN3@8W^p(15DP7~GMLe8E5$)u zi4dT>R1n<}=)U6(pmZOw+7uX=Dgt<^dbLI+uH6YV(FMd$>tJv8)e78G(n2<1e7l|v z_hk~>u1v#@Lyw2~%kNf>)-V4+`Dh&lj#fRX8m?6Z6W0mV%G~FzjZPBPdMCP#a{0G3 zX5+W0a?^mn+MfGv7(eSQVDN9JOT8+)0(Ww01#Y)$*U;%&8Twg8>gijW9UTc(_tK>; z=cdbAqDJdYz)ZGusRB|ICfBooxQ-R zQJOT7!LFWrj}<1~#!MVaiXyDA>Vt(n4f?YScj^|)_os&_T*xfyJE2qJExN~yIqPfT zw?eh$Yf+et6tOFnk2Cw#lRfsV-JLS`bovCU68hrK{KA@@qe0xFmfVmmkrN+nVMXZ# zerovQ7@nv`HTd4444Sz9wQIgRS*hE7Kt4z@^j<||mG;KV4{%>Aw?reb(9oE5YdzJJ zGSBjs7bcFYw9sX9Z_C!m5gV5BA)lNi>c<8iUo0IZ%~o6#$^*PX?VI#6v}}3so=yQ+ zIJ2T*2~G&HTLq+L@on)l9&u>VJ+^Y|awKTU+6ULe9tXd>$X<_!ls@Fkjy*$o=jV#m zth+V&5W7H&L`MIp>_Xygmo1FeXZV`jEmTN4D@vYR^v17XFFCAv*P)pYJVf>&a9Lsb zsY8Y;>5Swt8*=fMrvDA$otKVPq@D^OfzE|)F(K3AMGy<8fS+3<3^>1e^Yf=)`9%7sN8 zR$X&0KI_M36+cAIuY(N-9%^IQM^xP-30{H+S;@tlPf~K3Ctu~2V4?E0d6QJ`NA@$L zn73S3fd{Np^SB>jkZS|*J?!9m*t%$gG%MsLSU=G%xv~#5DhOO$>tEM|th-v3?3;mW zd5$R^dwzmrg~8i_*_B-)4^>|iv`V!L zy;A_4;-Zqn{SOLIS3KAMUf2ZV)ZwnL)4BB14YF{@|5tv@!u8!1IE7#Zr2E<1E86>C5H>W35ZQqbmmv^~0C`alpKt>MgxCGroKg7+ z5|@(I5!SnGQ`uG8-}&MyWMb&#!}9mrlWI;E`>xqM&9h`}{UVhyCb#@95;pYfk<|@* z6T6L1>p!{-c8UtqtKmRqf)KS?mm~BLRw9sIA&qn3N)*Z0&7N=4h6cd^=Q8Qvu z*L7WG`3g-PWvjUa_~1Yj!2Z8w{paEe$eH5StL8W9tuNkr2JgO0?f#%OW^vb*ipg-? zCql#Sd7(^>{+h8*`T%QbkBT^(mMTP@2v?;wI83D)1}f~-bvbiD>%ycDX+}K#1plm( zX+kiF@nqJJRUBn?kc%J~OX>>|*`!6t>kjpbT;keo#y9$wj15xC4xeD0fZi`7SU?__ z#-ZFn#ueOUedKEGrbz73GM+ycv&#KDb`UC_IYn%JxVmYH*p%s~u6MD=hCp~{Go1Z^ zEEE*VGq{e1wY17kl6ueg5}q3b^2e*a?;cBK1#^?vj10JxTA9EOEzXirY-~ceRPCo%@m-sHQ$E zAShRX`z*oDR;_KX5Ql0g!S1U`n3ZW0hd6P#;p?p>!iFYOVByDa7*2Bwj94*`_+ZN9 zxZ|UVhX*6t2qj(*9_?+2>|~z%I4>kNH7Xj@b!(G~>42;hQG=2K54o-&<7Gi`0n>0$ z-w!Q#8I56C3*S2l1o*F6>qcZ;_qXC&H|=gyiZ1!m5t_~>zt9a z9Owcd{W1+iM#D1B`O@Y?_7{S=(I>1j5xSFOu~;AIs7ZXTt!FPAII<4)*hdqBxHaL) zL!T=_12vOqmqGRMrw5Ap1IU!*Mc~ql&?c+~~wk8?f7J;?ye$b@7&Y4%cGiMqMrpM3#xqhH~De z*i@OuzI(f1!_g-%BJoP5#hce(5P?wS+NGN=4NQey;xW0lQEF2qAmN^{iI|2R|4 zn?VO0G%iBNgYmcdu`x-zha2myD0zDuCfTNdpkz&teW0B9bX7*r5~GD!9$dXk2w~iu zoL%YWLl&WCSiB3r}8)=3$I2c#PQPG1W*IIT=E&Pu&=uS=2pV)n+5ivV{7V!(m> zu0RL9wA&+OFL~i{Ha_u5aAL+4zXj!eCUJkMF=Q>j!ck!K1ZU!r)iB2tFG{9 zX+qYsp@K-u{F1rO`_>KVt4^-IAN`NBb;#-h7yj)k>9EWs`^wsF^U02VBAqHU;kIaA ztC7(;>f!eIe+V1b`@3zy=9a3){Hq;3gxNCG?q_2(1hqUV>`S5=sG)(+z`?!5-u;0_RlS z;aX1ORI(KqBKy^?TWO%3Qrbrx3~zsa_{KKI{+x$}+`?BZW8c>YDf9OMjFvI#1_IZ{ zb_q)f6FrZm3sI}LT%{!vp z+@Sj%!3DwG6<}EJ1DzOa->Od7^0A-=^tzA`B2sZ)4e_7^80^%U2?fR7ch55!Qpa1a z+;j7Doz|hPwF6^AtAoFtsxJGfR~CrX6QDD{j>iPMncX9UgH-r<-!5oL*X05jWQYb6 z8JCz^Tq<@SgUh>P)A4p+3wt%@$j8_SzxQjc>RcQpL2c3rpo_VcuZV^zu*l~E)8 zG1O`_lrv0k>RfSTtawa>JEH<8&kTkqH#E|n(!~{68cvBdr{^ppe%EObmK(!TAW$vSYO9u0W@{N+Vj`Y!CEJ~8LgDSfwfUF>80MSIcFx&dxi zE~mB?@5W0_GO)lj~>?~U23@o8QJ?PCip2|8}I{TAeQPS)SxT+FSKsW z4jr-VPC9q&%{nCcNh+;jdQmrxFyJ@u)_nr9-wsY|Bqq2l^>)hKV$}!5K_}Tf1ze;B zLKBJH6@OH$=-3*)xffE8y6e}*&pszjyCgAsH!m-1i`?gtF&15>@>th~wYli?`Dmg( z1NX%STYXvxyyCa>)WBaW#HDM}b-^u+1sTxdN=@QFGZY0V4eqI?Gk|m2f5X zZLaDB-)uADYcXbYGyA~Bz(sFs(FQr9?(-GtA5W2106D?s=B8K*E^V7{UPDAUuaF?< zXbew0X`Oed16p>W9ym&m2B)1~!GZb7lVE~CGFS%WQIcKN`CS41nJ>cI9D68pm1Mzmu?A^U6-1idso_qg!E8g*a2HrDURRI zgYRkE63O5vZ)mZfEJEW`(FSb~3-W_BliLHZ;j08bYOsPR3Zf9TFsSp~oyf8(=KZzG z)a5}%+^Nr7qvRtbdX{X3u>?cGB*fqNtVQ1dvf~zc)%;Y8|LkBk<9(X!0d|b6Tjh}A z>d+$D1w=^B$t5jiIqmrD7O`d^hP-z%i{-a}b#=hdz?dt)!+)WQ^Ksk#bP_A)ir(1O zu{k)8=&_Cf&e%FQ&2FlYRT0AKB3POqruQ4W*U6bPhw}=CC$Dgwip6&UBJpA~w6Psh z)uXA{65n^l)s0ebfTy%eJoGt(VnPpMnA_##)O$x|cbwHTVig8c%=_z*?ds*L`lsYq?r;9MUI-yS;`UzzHd`?zT;^SM zTF@CT^79U}IBmE%vx1TkZwZp-(M6pzSmKwZAQ6`|_KppTLn9*WVN zafk>o^8OMax0A@T?WX$8dp>zRyKGq6)!Ui=W{}2ne!X-0-*(apN*_Ga87{?^8DiKN z`>Eaj?2iFoE*g3Q);G2$YvlM8v#h`9;&Vce){>vfzCHSdmk*El-YBF6x=PXtbvs`@%2|YqeElW`J+DlN4kY+IheK#Lz1) z>eoH;6@-(q=}Ywal#aa|$OMwo#cYz%cn8UqYynl1ueYToi&{a2Lt`OL94QQQ&5vCb z%B1=w=I>2f{BM*sOCZVBto)gz;;!vyX}uN?*2qF4&-<9t!%`4}i1?lNE;Y zFHfGedR{%uzl7GHs&pt4>zd-cn-xUz*gHzO@vyKX$gFX4g~5Yd@-(w5ilk~bThjV& zTAZoSnEbIHE2~KKakd%?cZz2P*y^9A7hS0FS zAlBzXkKSA9w=?_M2p>d`<{p!s-#qX^&~antocIe0kk3J@ay3?#y_d8S+1Kh<`@DKr zvcWrWXg~(w=V39a`HC*fNzE0w?W_2~PIdQ#nHi}MPfb~FjpYv?Z1xH6M)zT$;jkdt z(>|C2WwO-#6o0oOSQa|`p~#fCkr8B-$W0ADumh~15-g{W+~1fwP-cvy3n!3m z=|PR}CKk;aT)%OszQ%^4$tssyQTmuS!Ota%*{N8vE<-y{d=nL=e)#lxIB%R7D&Fkl zC;iOs_9MWkuBm`#{n+#Tqh`=9N9*)Rw+$+WyHNv#zS8=sdY=8l}_b zf&*&}*Xl0R3q{74PO`;cDDvFrBEL~2IJ`=f1XtyJ+mqf|zAFSx0_D;Z^o>_T-YhX~ zJBp8fHnfkK$I8g%Pkrvx)YX>!tgZ(H%{3q`&Xa82sK z&CRV2YeWL8j7@rE@kO%6@1`Qy*L?~}vF|Oy<`Ll4(PAPtc)=h%^iXPKFNv-sMwNB% zYTFzH`O?qS2!f?GZ67p0Frce>uyB^;BM3)TYs-A=*$ zSC%ReE$tfiZXO7^cfM9bOZ?fs)gRwZ9WRv}u`fH56EfSXQ@3k^y_N4a%;~3E=lvWe zK;7BSy`@&}QR!n#9=6rY)q$JQgg1mEDd1z4z{5SP+OB<-ZVQuBj1TFkE6bW=@>c}W z0d=b2Qql9s$YqZ389Tfg+Ni@izOHToaeTT4Ts`}WO`1u?7|%-Tka9G=3b6 z6St~!z2mZSw08Me7GY5?M%&G>4QELZCxM_bZIe8?gWjr~R+;wC5#f%k7$-Rcq}})i zC`QK=kdkq=N?bp<4u9+^|4VDV3vS~P@O5dI{}f+_Z*BFZ54zwwh5GHR8UOImSa_0G zqXJibyBw#Wx`?C7Z7u>+alMc6mNPAHKYCnwD`d4Vi_cXWdO8Xg)0|bV8O9M3ZDYE; zkCYTkAmQ9V89Z^%80^XAzWoSRy$&Hd zGU~BsM94wZ&WQd8NdjUOY7)egUEyX;wpXZf6cOrsND9wf)~g;qda*~Gi-n;h4Y)7I z#7Qo1qh3gRZhExUHfgk}>`HYcp`dF!EA^7GD3P%+Rs`R34TuP;Sv2e|Wp1J=5G5xf zvT3=m%--gnJk~5f*>$2A^@NfZ7Mlkg^nyNN=#3=Ha1#B+tre@|2rA>xzyjDz9Oq9h zJ66Kt$1=qa9BHJH1|$~F<(7;`x{MAUxc!7pxSWFtUI^Kn_T10E?)WB*8e|iTzh6Fk zqk_>&-WWw7IxM9Tnx!Jz_t}8!qQW+i@po2lsKl4(yd!lysYz>pg`d`J%Er6;LPSx> zF}q=7k}@GxENo01NC2n6nk$&c{ehlvuo*OS)N8Vpz&(DoI+}2LGq6A5qqAHTw`scT z*jV25Xmghlxoy+*AP3kEc1jak?fYoG!f0`C2BUKBSw^sfOxH&d&V@0IMX8m!hWo#- zZyIh1FC4LA=HUjH-QV*_hS>b06&YRl$+vDp=+n_hBcjJgW!yRwnP)+vR8+^Ra}n#W zi%^GDgo$`xC05?;O`H`Ls;s3tvUOV5jRiKtlG6iTYcSL2Ki=#7Dl|${b@>gshEKk3*ujG~{dPk2tkstv6c`nxHxn#=-MD%YOR$Dq#inlw+O&<)J zzAr<|W(-T4Ywi88?eMW^%(d{=8(R*oKli1BMAdzEsBGtdeA^&A-wVDhAdK_90RQo$ z|K}gEbrvm^es~{Vxe9y*0t9VXYj5*#jcXM6z66NO`2qM|1I`y8e7gyNJHKzgJ@DHD zzdi8V1HV1++XKHn@Y@5wJ@DHDzdi8V1HV1++XKHn@Y@5wJ@DHDzdi8V1HV1++XKHn z@Y@5wJ@DHDzdi8V1HV1++XKHn@Y@5wJ@DHDzdi8V1OLDE0Q#v|6c`y86<8hmvFM-e zLt!2IqqP>)p+DOD{5teUd-uE!{n6e&t3!XbmZx>-cWch8Lw~lWCw1tL*7&#%{m~j8 z)uBIHeQq84qrG`phyG}F59-h#t@eH$`lG$RSBL&=ukO~NKibQjI`n_u^1ySt0~7tf z0Wh?!gcJL$p7LAGK08)VtkcJ$YxS_G4KQn*3c3c^YF%a2YWW|A*HJ<(wUtl{VCGti zs2Q+T%M?&kO^(TdX%6LooXg}NMSyi^V~S|W=Y0y9`Fi|Q|uLG^&))E1(;svMI> zb+FQ?wu%(01#FqJ6soBt`OP#GB~Wz*33Q440(3F3MRMY(nyfgg3JfbFhGG|rp(+bS zQ6*_nR8dLQbi`2Pw6qJqE1051<0%JVm2fP=05n^zBl_;d2h---bcf9ma1 z{@oi4)zI}I{y$=XlLKtP`Tv#&eu)9aKk~p|V1SbYR{RPBAP0QU1HZz6hN2|;OAK&w z0I>fq2E;)g;N*Z`Vc=U1_?s~huzOSApLqcMZ}0w|8;E~h8qvLv6aSwv@VyTF6$ZZ5 zfq&G3e~*E0bpX_Y{}u*79ayIPy$<|0F#zhoKWf2Gc|Zcxf^T);7Z~`bI`B7R;KSXd zW`F_m-xGb1c-l)r{5|?M8vPOf{}cv(facDYS!t1 z?oCFE(C-*n|5GjaF%NL~;2KUX_yqj_5PZ;>QFZ>w;Klg<{W8mk$ z@J9^%x-a~Wfq(7`|8Ha9&wh~nH^twO6aS;TttYck_;X%^6aQ;ukG{<- z7NdWOfuH)q?|k5UE%=xE(4T$b9#b{+xUD)Gwm}081?FkB7+tNc@LM1HiyFewg#N4n ze~TuFc9f;o-aq$|6aSwv@K=4|e?=c!y<7>U#GODpUYDYu-@X234bQ+=VtK7Y6Siri z+l*BHB?f+_4RGqgFSUU`HNu~@fn|ydP?JSc=n7!QYJZrKsw8R%%m6Ea>Z@>U0jj6G z0L1~*Ra$^9R}}wd+6rPQ$F$_d&}H(XsHU7Ks=+Z?5ma491eFrz`ybN>MTG>BKjUxp zcjN#N|G@FaCk^%{f5iVE82F(l__;6SV8G@-(1$jz)IwiU3(>#2v8E=_ywkqu`5ii_ zuk{jim4@6u>%_n63xCjw|Fingnq{(R)Mm|Zuf=)2|1BeJ)Bso!`yatUbz1a$fPuij zDgIUf19e_o&8NR(fKvy4?g@Uz!1p@vD}AW4wBWBo|4%=APkn@@xSFCd4$IKB%N75` z!2f|Z@Z+oiXal>fjlSice|pjXg*zNPzr1_-+h|EBnha^in6 zh%o42vIMpNp$`1FFaWfHgWGNY(_S9`(u-yt-~R1f?zdR1st!ZCQp2f;ke1-GAF0SDOrTYQWzSf6i-w_~$*n91gxp zX$k58>cGFkz<)*`%D8;?zwA!V`QhYd4nJH8W(R+XfnRC^fDinn4;AG<{V%_V|A{{+ zN)AJH|G)OW1UiZ;`y0kl#)WZXk)Q@e!m5B_M@ZP$ux|lm3j}0`h=3q8J3?3$A*>=A z0oi0x5Hx`h0@4!6XrO^17$M3G^N+^K`999!eDAxzSM{o2RaaM6cS6I=zjMx`(oLu9 zz58z6d*APFMbrb;!ovzx8z3?mJixA|IIf@kG^<-9?0?`qAkG9^*RBYNl&}$@4`3U1 zi+oN^2H|9B+-d1PZI@j!f#_CJPrz!}$}-feF@;150& z=>CKJvTZmrsxrkBl=p}m5ZC~Z9Uxs`h7T3PRtEGH*#8z0Wt7-~BJjXA$Ji^h|A|4` z{|M~AV?>wy?j!^J;Q`raENsFh?@SJecJd$LoCsMkyK^fH)Iq=RzY!=mj6Ta`DF^lO6Vyunh+^ zs^q}~ny*MY7eW>we(31oLq)!SAYZUz#`t219}2oJ=xR!$bI)p55A4599R$TEzstp(%U(nT* zc<6whO{y@32NXRZbb*H)u!#@t{&-U$kCDgU$hKkoS1S7C0pLU6fndmi-+s$y^XJWF z&y*|Ujv*|D*pZ<6f^t$LvHw$FZ(GpA2M_p*56zl5oc&SoyT_jT`vz>o-HxGL7Q{Dy z(VPdYumJ-;ANeyuW#u&0-#}5VF7nGBl zbbQ<5E4`XVFf$$~3N`?o81X|zIUCB%AZ$Zm1^pX_^LTROxlk8JXuyXwzp)lWcK^i> zg_V8swrT@J2jd*Ta#9ltvJPfq|2=rX;#_FNiM?Tj0v{UDyFL5m#?SJ02J}1hfv^oH zx30qKQCy*S9{A6UA5vpNgX0UzNsT5Ra8BsmywJ!4#xsEtC-w&)f*k15v=%$OZ)ZUJ zZu}$omj!Ov_T?}S9x%g)cy0;l0<*jl5j%od(t9006jWbOPHJiFf8wNmw|c*($N)_a zn4Amk@PHXUB;)|%2p7+sTpLuPRUpKaS{6zu`M zhHa?D7)3s3$^-t!4|&898uCiy97C(zBIFqQiw_0W7j*4-47+yRIk-*jJJvi*`?ElOm?F(ccfGr^G0i7H$ITzZ&2HZ6V?B$oeJua@;ZNt&gP?k9Xm!~~Nb2ughj_S1=^wB#jMVxy`tUp#QP@gXA*AlG>Fnq_uWzR%Cd z@#n8M4%c`<JJq&J`{9c&`&243V!?|vp@FV3l9Jv3?@DVK5*Bds>sF- z?!|t&UUWYam_*oyQz=iee&w=$=a&ToAG)}6CF+9&#~1X|iD;4m&N1B@-wuoi0>_6$ z9H|*b2p(uI)g5WyusS<&%y+JlPeDK*K#UP^!zJBou=eCf@`@2^K4X&_R2H!#zzBn)|YLaT_0!a=8v;NSb71LbA1HthH<)%eo|7XW_ zED-x|B?r9nK#=euBM-D~P>r2CbIRv)ZuJ4251|L{7knsTKujL(e@YN-fRs<(9iKO_ zMGa=n1LpXU6*d5ju(k!Ko3Ko0jbP#p0?X7~`VPc7A@9n`Hg%e$WIbFa-lfE+YqeQHe)$UbAK zKK0$gho1WDqj%I=<-zd<<)+0$2MnUUH}ZgXCb$dukidwIbw{-NLli@5JQo`AA(;o- z)~^=u*#Pk)#yCQ+*npS%L&b>?Wo%xMO+4TTh7MpqpNyp8oI0RoVe#@naPT3)1BdqR zFnhFpzL%YG%ruTL;P|0pz=zhn6_-Q%AH2LE+W(D?5jO|5tijwoP+hYJJmkQAh7WzQ zH?TPK0?Hrl5*5j8=N8GjAOMWeEcYS z0pJ1wVFPywA3|P9pg+^c4As>k6TK?Xvqt2Vc=AASw`wK;3_H9x%rSAPd~}2K04DiV{EcZV~Fw%$YiY$#v?jY7>J8jOW5&#Se|@ z(dH(4SOr7=;~wmK`hm~ipPoAe`)|SnX4nAt8EW=`IS*K21A*W}OWsKc^s#4ir%iD8 zuCh^|+A6o`Zs(Up)vZ>b_Am>MFX(!@<8tap+1P&%9?i!4E7j!*6hGc+qXlrHv?eKudxzG?tXca$%x-(vD z&rpt`*nfc!jqcYm;OG9+q!pfZ>b>=@l6u&A;{i)-pcwI?!>ebwhzEk>3%Z^jf&HHw z-?>2W0M`SuE-;Y;f%AZUd}vH;C-(0E>&pNeXe!~v=wsN>q;HX~k6|&^r}n^!{lJG7 zj~$Rp`yV`C(Dn3`PnS;28``=S*8!RgFy#RgY(U_|#fT4$?H~Bw<9yhxroa8micp{0 z3LB7fjlJ-I5g+Q(JThPHYZ@G1(Dn4h^M}^Cu>V#(5G;IX+}P#yo>x#re5hiX$M2~79~@uMjZ^V|Ts)FFOx=GE9#HYYVBkajTGb6$ z=KuIz25Uq9BRP(c@4rR=GOONI3O-ke z4d>f~S{M4u1I39C^>1C5U3Fy#WbdISC2G&;de{}AcNOq~dx;MvO^?r^{STfmi1vTY z^g*|VwW-DI@<5>2fEhkCp!KWl>ZQQ{41_JGN`P~gP=;6p#0 zI}?!1|JSeA*??BHi?6r2jsEuDumKTASe*FKzrNX;Njwl7U(k(H(Xau=#MHl2R37jL z8%Q~{C!oCtE-*T_qpr6(&oA;be#k=(+(-D(S8LvJvG4W-#}|~BQJUptIG0WAlONaS zWoE?##f1;0d=dEGk0E?OV1y#q*q{6|5kJ&K>Sb9pe5m+)o6n5vkw^OSEt(U34wTX?jX9N%2Q+%lGU)l3zz1OD( zK6G~5l5FCE;P`^_G9s}53r58h=y||>Ch(UBWPE7dqQLil745w-cBIHW;1wGP^Yj@@ z*nq%^??G2tUC@&*r$FfOz+Wu?0z>Ej%V*~3J2fp{K=e?!*jEy|t zZ+&VHIpCEC?hkyZcdG{ZwEs>T!SMyA#T8f2VN?#`3#M5gm(iUy7Ku4S;Pau@df2&M8XDmvrn_z#l-`A zK3wDX{sS9O`~><~Qh(!z#JMog{4yCIYC!m4gL{AvZF=X89NPcj`GRQwKX`laE#v-k zIbb{&5>{-K14ewv-~9(R;5~-Se*DmX3qCZtf2W(O4hW7fC@&-F>#YlN%=X_G518RY zGe`8W{rsOjy4U~O#CNg&kQ_tC^?=tHvbz^Q6jdjpkY(P+msDl@p(2d)t3g z9`Jz=UHJZ6pFD8w@&z`KV#)lkPaSw~b1m2SKF5dn{%7tBjxQ)LBN{fq*e><&*x>;? z_|Q8f1FX&f*!#GS_0^iBo;+~3^2=nOu`YH*twnct@geWIMLfq)!iSEnbGV2Hg6j*K z)Fz@Sl9JDORF_69?eJa?Iq>CYTiNhV4U}4RT3(65172&-+@<_79S?ZL z2JSvSR7t8i0gQ0Y$liI70l|m`z&+^sKOo~k-uNIc0Bm4XmxgTNq`_$Fhb+G(3oTBZ~RcqYjp}#9T0S1khi@T?+3yI?s@~B zxkdLPzf8u5TB!9X^>s&{WkMI+3w)?Xc)2_3{@)W{kl1T)S2G?ko(nafE7C!V{^0I8=fuQ<=W)5ys=xxu9?-v&j_!B=Q#}T5J z<$p6iwCc^Fx$OJTgX#;~GH=vP<33xx_J|v>fe)GK0y7@)elCTA#NJX7ECL-XF~n@9Waq)|E;b|Be+j$hC1%d*;Uv;VW=0W*B4c?p@@^_1Ys zfAt*5u^@l-0C+<1fE|2@%YY)(p!#pehnm!S;r9QeC1=h#n5?~`c+Mfc15 zkKbwk5g#5;;{Xk(?Lj#O$ScqW)fzy(0c}wIA=Dt!2Gt}*T~ghkeii6h!3Xs(Lk~0E zpx)-_Z?282DNZJjzklOo^0@M~lgZ=qF(;G9rK3(J57$>tCXb6poXj{b9Ck8!WPj;o z^7!!!CzHnyhn!3ve>>=8^2j>iWbToI=l)*py^$9}uR|0FQ6NNt5CuXM2vHzJfe-~k z6bMluM1c?mLKFy5AVh%>1ws@EQ6NNt5CuXM2vHzJfe-~k6bMluM1c?mLKFy5AVh%> z1ws@EQ6NNt5Cw{d0v-vqp*Jik@P8$;m!wbrCcQ3Ud_CLn|51Lv4mW(>#%pnp{WzpwwF{Pzzq=I?7J|2+s^)YlIA3+Vg&eVr=*{cOhkeSJ;-`zXeW`dY_; z;lXDZe;LBp=lx|6csRWd z{rEwFYQ&w1ws@EQ6NNt5C#6XQ-JdPVkoySh3EH) zoIa7uC-V2q^7cfop2*P?xq0XJJ1H*@H5rtFI*m%LM$~IW?+#@+cRSU7UQV^Yx08MQ znKI7obTW+7JNy|*^m)H)g46m_vJWL?cW+wl4(i^Z?h*Rtq2?9(qco$O)~3`Wtw}Yd z#u;kf)}y*ss9{itdLq73iE39+&N_OaRe$y=R<+`j3_Y(ZQ+_&npN3P-I`lrS`1E6} z0`=kNxFA_Hd~`vr-Q}z#e?yPwas|m1HF;#gur{)(9*6 z^|RvhP#adM4Xn~Y?HQ-hfNK1p_Alysa2im}XCn=25Dm1x zUlpEY=>5s-wy87-d+ITUI{q3BsIQ-n1`h>J1JLT!hI!eveuqELG}gai_Q*WZKL<46 zdCpSbJoLsue;m|41r2y#B&vH{Ptf26g%41-K+qt9_~4}qPiQoFo@nqa@qtEz$5lR1 zX;Av%huEXw1BnKIDp}Ij{tG@C7SrM;t>3S@$h7{X18ZjFpmzjlfZj3IGzc@HK{-~3 zdWGXz;52wn;R78Fs0Xk&8azofc$}UEnFbI2`2qH4dKUblLACI(LRvp$hV5s7@}T3d zrzK~_G^osw|8As#sE3N$SItQlbg270d%ejEY#@yeb)IGJe#wFcO8pAduE4VpL9#&O z15Sg|>{*fpf)C0PA3R<9VJ6eykx~z`zYre;LW6%E*_cV|kFom<(E6j13qGWM9_tqQycZfkFFwV(v}x}3JM8?&@Bg^L`9R1!vulGIFBQ=G zAp>mJg`o92E*{yK-JRCowV^o;-W<`-a*B8^woD(yMn+Yp{us~j`c~+NquB<}J;h${ z6=V4wcK&lj({P`*fx7-^qK~Z~T7L}cL-e3}ae@Yr1u`E%C!nXaub-4p-e*(VMzH9b zVIKBT_jXaf{@n8aZ{Emd;ZHx}(>_w|0NZsTsZK^1)<5<2wgsSpsGTZk&{35KpuwI` zHd)RQ|M|<`FREuS^4A8E@*oHL?NF7be0brFdM2R@uX zI#2W$@uUICU)45nOd8=K3ynm9Y)qavhK*_Q5^GZR8Mkeq+K4*afb3*%w!u?g>?14N zpmqJ1^YIMWVt(~QwEo2J_P*zmYw3zwS#CaX+eh80$MW}QGmOjjc%6A{51Z4g9&7(f zMK=wEZ6Mo-e%MF8Yy+GJR2g8qHZIkVi7ois!A#T>6*Lg_BSn89Gy7=k+7%vaHogJb z_`$etY)I1=SR~bb)7gl3$v(Qcb43=>z`hK)c02+#bSCwQD(r1S1I;!NHlk!7jqKB& z{c_`HIhj4|-5t@$QY48j>0fOzb1{n?L;dXC7-dz5%;&+0d4( zcm3y0?IU3$YG-Ca13EK5UHUI%Co42~jLu7s(3x3#7XI`nRsl3=nWfWc*0RP6EM?4lbYO*I5Y93f8}9Opko6 zwj9XA-QSEdsk1*MV&p+pdUR8kcVy>P+e718_{ha8S$e|jcc&9uMd0dz3~k^4>%8V z+(2g=1ZE#Ks#T?cU&``q7gH_VFW4ClG$bG37HmqwVSesc8aa`xaMBYX3gtVVH`J*@T01PBYL$BeAq`Fo7Bz6GhlcB z@j0qJ>G=NOTGwE;FM*B^RNKI-jc8#XS=opG$orXfYFLfV2TE;lJq-f4k1AIzcbof{ zzWvPpS?GFt%pVsHXY&3GDh&ow|5im7(6bPLee~6S@3t{;#n-#FR{SceZ%M-ug>Ol= z5&g7}F719Vi)di~EOb3R0`*9z4{TMa(SX+PNdtTK(Z@+EJ$PNbfwd1InP|tqrumjs z|C(L?b`-7*a{o#4YhdT-uTtEIE0 zvl6&p1^u`6G|>CkBDs%I_?80qul?)m4>O4dv37ZY>JvwzMsY&#*KT{IffxH|$+Xdy zYhO0|P1a8GEon3${~GTpR9&S3^_iCaYf69l!2D}R-hanM>-P^2q4h7D*e5@Zc)*GV znr%SxVCv9r?B5o>y&(^{oh;!;!Zr~05on1WlzJ+i>I>AWFJ`BM`koYyn&GhvVYBveblyLtpYXn#Qs@` z>U)d6pP&J++pqR*(Db5OqyO#U-7VMt&7s|_tA&3};720v1iog@2U5%hr$G_yBQ^fU zzHeCVdnxMI>uFF^(F^Ef7}Jpb^B2W0Z1&)zZ#l;iZQ@6Q23D~*;#rXWYZ`{;#XdUw z@sez!fy1^8RBF6C7mSK2Fw#Kj<)zSI(WD_}%jWNi-pv9#vGT8J*a=~1cn-AK8=LV* z!Zr}`M@IW-`J_R)w0{52LU|d<#=eJw4}>gOG}(OpXTI9Y`jbp_V<(>Wk%&7Hz9mir zDfULAK@sgE#NPC4(iws-3qhQ7w=Zyw*dp(S<_2!5o* zV7cuhp%c(c$Zq`6-w&+KA{y8~3*}{?=a18@@0*bZ!cNv~L@)M{z|aJCV(MSJOZL$g z$Cw;{d*-3Xg|~h;cnj5TZbc0wD^7 zC=jB+{Z0YhfxQSX9DJdr)S?X!c)6BT-}k(xDufbMH9W4@)c;qnvyE4^n#FAO8fCny z)h(jbYq+ib35 zEBQ}RC!!9GAv8pt2uBrq5&8*HAVh%>1@0pXP=2<P zyOca^N{bZLX47|zXgw=dP1>0AAojk9Ya%$o47J1bory98; zl__@){tV=aAQqPA5%b(hB^DUDqlkq@4mEN^p~lGD@`)l(IKE5cLM7hY zofC;Q2rLe35SX;G1|a?8sfU zlgF;^floZ1ax@(q9V7F&zevha7Hfcy#A*#9FB@y%dFkpJ5K}B->yc}O{0hDXHUAcC zFw$Ipt>zi{j4Pn|$DG}@(j{_ig}+PW*TUb|k>Z5EIq(@nj>IRc=CbD1EAV{~d4$F_ zgwq;ct@Jc&RJjbR|H9KOveHwm?(|x?5dEVl8 zHBTUgUR(Z9eq03dWRV|fwg$xgA2!4`W~Cpc`01LohH^?wBl6=Zrc?3LKEbApe?vCM zEPvm!Ai;G0G-;;B`TLebS5s2P_IRyOTZ5F>2miZSJ{MxN7LD!48c^R~|1tIN8ShBX6AAktOn?5a)-uXW_$c|EjWv0Uerp&6Nc|ZCf#i@*K)*HA9N3-%3C7 z@EtYZ&!=CT_P{wZronB#1~rdCzXs&}E4tyswaW$RJ+4_NzhYe)RpV>0qu)e*2XFdK z&Do9ixd+#dC(j?%Egvxjx;3bA$431&X;>ex{Di%jJ+cq^j?3_T1Kavd(hWjK+ty>( zjwkG1`BtvTDKT4vQ8&ait!bG*a&XHk)+D05wuV6TThA5^ZxIjqjFF}MpqO)?zwbiq ztMK6=wng}|&2$5FH1ykh7Wp4|w&OZB(yamd4f$U}N26{IualwH%t4-q$a@Pb`xMW4 z^~pa!od`pY6OY+5S%W55DUU(k2k1AfVOY<0?6Q~q4e-;txe1iJ@HE*U6Ws>dfTaV?Y9hfz&Ljl$x@{>gDt(k5>-a7P~h_me2s0Q2l z(FTuaTD)`Ch7EBeI?#e=r^$sBCe@t>xQQJKv&5IL{6m0lgAo(j=XLS z`m;~d+Eoi^{yxt$l;08gNA}@N5vQW9LCyK}rQcdh=Qrdtnd$58AFlVQ-;}&&{TkF< z4WBWZvQ2Kd_dO5dojy7LVy`yWhUrqAmkr&stK{Z}q%XkJgo_#7AbOS$w()q1x^T>RP z^Y(4a-8dC}<@mO25yQy$f#-Lqxn3r^0rp;OtGev(u52MHwJY+Sael)Yl-CHO*mY4S z&g%ST)NeH^Rk)2@1)uc4ajG=p^GCuC*gzM0T(gWK0* zIVN-eH{}lvjd@L{-}oAMyr{cYornpN&u_?~(R72P-!{w`nM1MS@jmx};=&LcD`KDI zeQ>Wq(QiMVJEQT6_yuzx*S{0DGtBgxQg2RK18^~{LDX1N&Y((dF>MX1ZkQO`;U?jG zzHPa@j2IEyYFvXXSC4&E{`-&L*~Hgl)U%KK{ASc|O(~Z{)C}}ogQtE2F4nAe zl|q`oZ%l$>vgFuQvo)+={I)h{@eAyBR)BIRG&PWzr)5e9RKy!1vw&) zQC#^N)ZDi>x-?=7CkIQKNM4Wz;qAVDmgdW8Z7mjl8f%^{AQ)! zL|r0ad((z=y@@)uzW7I-KVm}(|7ncU2@e(C?{Fk?DsS+i4{Fkrm10_oE_%Cl)0={|tm&KJ~zA8Y@uQust zq%-2QFuL)tt3>}&e;=O+5&u}|pAZE?6!;IK0QsPjf8M_)>-46%E{qHsr)Z>an&&!6 zBW>e6*9jWO)seb!zUv$M{TsS|P2(7iqZ{VCj?g$v<4YP}&^Scn;CdPx7ARxmLf64f zivFqYDA7_zY$T#jub!Fo_H7FE56`Zkgwo@=O!fMpm8F#FJQUe}7IqnN0d_%;{ zz?TId3gVVTybNs>#HPn6{pcfiE~fA~Mq6zs{J^6+H!S35Q1Yh(kJ08xn3#xBLVS;y zqc}VBIZE+WimytkH_H9C6w_no{}=O}G@Q=dK4=IZF=mz zUbE6O9&<$PH5y+1_%y%B8wWnf0v65B>RRkXIQwA99FKcl`u;Q<)V?9d4aFQ+CocB* zoY@=0dw24f->JQ8vuS=_v0a*9X&TPq)K5S+NAf{-Z*E>Q8F<|Cw??qY7t8Yg8DruG znoURd-f#K&?73&kc*MxfNr=m(`B`GOG{5AzLp$V)9CVG2G)Kf^d8=uh{>3iVp?-uK z!=%O}s(uLW8&zZZ5JLvvt`>_ZJ9f8jY z*|=!NBvW6SEAuq#)F6WQ@bE`|ubwk8hvsML2Zx__=D^kkqRy@oL!qCeCL2k|#CeH3 zz_YVpQXH#EzGA!bdsyF2H)(!}-sp$-X?~86--*lPHBbq!Ma@Uy*A|$$kc}KKSLL_2 zxB~d&o4xWP_qT``UJ(xgKRl0pRpU9TzZ70b^GoqDznILA7P#QMhTqp6i=x!;HeN@pkrkDok+FMj6a9=?BKN@MeI9j8o|G3DjT6=RQXNwbJFl`E1caG z`OB9{Spq*-=BW6$^|Dc!#B7eTZF}ax`fQqCwB;U? zuREb<HF`XA4!`!&j)OOFL`@ZF8RK;inr$n~Z{e?1d~D=z_F{j-Pg^_U`P+y=@Ug#&EBWm)N9sE!Y+Ivjypp~%i{|LvR&eevjd%;;HxqLl(wgQ-a!39t zq`H11I@aU0%ye?cM1I3(j9d!DfC#_6agNWC{NA+mtsI)4wY^I5EDMIU_ozVzxs!He zAD<%THf>lpMGuXR`9C-# zc%7p`Huh-Uz~}rhcZxSj`1Qz!tnb$cy3W)1en+ALE{vS^qnhRC)JU*W2Nf^jpH;@XyWDt509`s{2PxJG%ohO6((*Hn5BujMPboA_&7uhB4G$=$@?#})o5FQrEAZm-84 zP@Gom#luR!P<~D!3|{;o&y&t${JRHHzdK?7!*0cSIs1n!@lmhW%tPCFpHtDp%Y*(` zQz8*7Hn8Q(cf>gavBdIEcFI1sZb)O^i?a!xLy(W&u4!HQBVK>M{^Pd{>!*XO zoSzW0Hhoar0$_re!-RpIJ>ufw<3P{ar9Eo0j?^m|HCiwJ_&2Zj760+x>Qy|~6gm8A zZmb8EO7~CtXu+5~;F72xDd?~-d9(N$?Rt9W2Yf%!n-xBK&UC=>WBp99W( z5)O|Xi}Ox>e@eld*pFE1O^Wjx(gEz;vsI1JvD4(P`Kt5gCwJM7+eGe>?{1nNnrwq8oF<>=c z19MRP5pJyijeZ?G@=dTGkO4mB6UoT6Q-|l!{T&{AkelZCYV+J28JiTiAM)^I`GkI< z#+;Y&tzJ^G0lj<*SADRGjQk6Gy~As_2v7DnqY*|P^UJrpvILeQ=zuwJe**ENkWXLj z-=#ed_+|b4Dcl!a4{};PS93g1t&aeV9@sK)+lDn?Eadv?>@FSFNZ4K&&B6Ib=g2$S z8DGswROX;Om-|26qPus-;oYni`80szaEyfT2goM{_f+ak$QXP%!aRBZinF_-J@$b5 zv?NaGoj+8?Yp@qG2K(Opsk(cgKC*{(pff!8i4)GQ;WR$xaC8mtAK|HsZk$Too;WcN z*c;DcAw7F$gJDK)B8aW7KyVTd=Ycd{fM@GuHnsE-WpZd0{=QXE*=Af_5 zjM#hlM^J~^7;`V;?GbB_TFZ#DM~!8~*u$Q;vgyz7_mIQJXCn0azncP@a8ZAu)dCIy zqSTWsoaM?5(Q?-%3efcTlIqB?YD_zjFkngZJpyMD{q33IpZh^f8{faX&Y%SQ` zI1fKecE9l~toC$w$P3K*X6r84cen@SH|m5O{%AE@)VDrs{j$<;9yJ8`J;ROq{ddkpE^Ojn!dA2}D;mdQO>8>)>2n+x~=>@A#wP?rsH zDTw1LN%c9@^SI6iyztegGstIzUdI^}F;KuG_I$EQn=j}EIt*|20o3cRkjGdMLwgM9mJ|197I} z9*3wWw4e{Jq#I*rQ?FOptGEZw4dNcK5z*IOu8W1WEEpKgV-xs22+M(ej(Q+Ct4$f$ z1wEHF8;$gDBzmbTcDZs^1!jOVBCs3W1NN8PFMRGBeYxF*z8yFl124ioa3*bDw;F0( z=xng_=vAuvlW`svXAgc4!e->&n~1f*nFls5a4FRMK`jB?1F><>mVNvVopp3J7TFO= z=xc#{z_!PE7x%!K|LcRhwS7i^Q^f8xuBP}@`90_v$34U|jyeSyn-`wZ?E(3JXAWvp zh!_av9!ihVH4EJ5hoc8}*_I=T6JF0Hf1-9?hkXY76t*$H2c1!p7Q3ItLl6ahkcLq1KF;Jqj=;{t*$4JE&VT6n3OQ1p zoNC`U*T6yT7$HX>t8fpTZTLOtY=tug zY)Cxgz#+4Duhz>t%H@}Pn<%-nN?Z@@cf@&c+g+6-xCi0~aSzz44JkGTb?$J6#XVBi z&(%L?l&72L+;a-~_I%Kp?fjv2F7(;W+`q3;f#1T93*GdoTQ{Xi zy6ImhJ~<)tQ0RA03J?#%cH%?vIKk_L0q>GB9CTGiNxGISk*W>FpOs3Vye19teYnC7 zD?xH3r2Kd32h@-%a@T}kgn`zp3(;q*!OP7P&R@v=T?zbS;6mmd>-GoC20+NwA6zfXHHu; zN7D(U^TQ5raO6NA4{8_5&^uE60LylCuEwHkhABFX^b2GrVu=)8UyA3G%pch|m*yBD z_T}gF?MEQT6dhlMEqrT~hEc-?N*dXQ^=S~!zZ0?^G7@$W@IUC?PEDzgxK!JV>;}j9 z9!+k;ZsJjd@@nDF+(wMCm><~*u}jAH%14a? zp~Ha}tyKFbqsG+04vjfR1p8UooiD2P0d#lv&Xq^B@1xk<{c3$8VSC8>boS_2Zg-#_ z0Jq7ZABZ>MD}!AFdw|!0aqiai=%tj8&Ok2!=bJI2hu9Lfdfr=#-3NXrTLv}&zEj8V z^qmR)JKiL{8LiEcFbn83;6;ev!q3`;(;0M`;CJmAQgtPC41b2mrXapTosjA zdjGdv8T*ZN7!ZMpG;r#d#}lNtwb<{G4FCBh#QLo(XL)V@M=dM+}-twSMud!95yD|7<@%$kE8)vZIktHz>kC&R>(zQ9np0o3Q5j#eNTTM zCTh!EJpV19H);?;9s)Z-JSSu!d@#@}!26+3e?7Kkqj(&yf4l1lUl&`Wuw(rXOycmE%Asit-S diff --git a/src/OutGridView.Gui/AvaloniaAppRunner.cs b/src/OutGridView.Gui/AvaloniaAppRunner.cs deleted file mode 100644 index abf439b..0000000 --- a/src/OutGridView.Gui/AvaloniaAppRunner.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Avalonia; -using System.Collections.Generic; -using Avalonia.Logging.Serilog; -using OutGridView.Application.ViewModels; -using OutGridView.Application.Views; -using OutGridView.Application.Services; -using System.Threading; -using OutGridView.Application.Models; -using System.Linq; -using ReactiveUI; -using Avalonia.Threading; -using Avalonia.Controls; -using OutGridView.Models; - -namespace OutGridView.Application -{ - public static class AvaloniaAppRunner - { - public static App App; - public static AppBuilder Builder; - private static ApplicationData _applicationData; - private static Window _mainWindow; - private static CancellationTokenSource _source; - static AvaloniaAppRunner() - { - App = new App(); - Builder = BuildAvaloniaApp(); - } - - public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure(App) - .UseReactiveUI() - .UsePlatformDetect() - .UseDataGrid() - .LogToDebug() - .SetupWithoutStarting(); - public static void RunApp(ApplicationData applicationData) - { - _applicationData = applicationData; - AppMain(App); - } - private static void AppMain(Avalonia.Application app) - { - - _mainWindow = new MainWindow - { - DataContext = new MainWindowViewModel(_applicationData), - }; - - _source = new CancellationTokenSource(); - - _mainWindow.Show(); - _mainWindow.Closing += Window_Closing; - - App.MainWindow = _mainWindow; - - App.Run(_source.Token); - - _source.Dispose(); - - } - private static void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) - { - _source.Cancel(); - } - - public static void CloseProgram() - { - _mainWindow.Close(); - } - - public static List GetPassThruIndexes() - { - var mainWindowDataContext = _mainWindow.DataContext as MainWindowViewModel; - return mainWindowDataContext.OutputObjectIndexes; - } - } -} diff --git a/src/OutGridView.Gui/Converters/EnumToDescriptionConverter.cs b/src/OutGridView.Gui/Converters/EnumToDescriptionConverter.cs deleted file mode 100644 index 8b13703..0000000 --- a/src/OutGridView.Gui/Converters/EnumToDescriptionConverter.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Avalonia.Data.Converters; -using System.Globalization; - -namespace OutGridView.Application.Converters -{ - public class EnumToDescriptionConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo) - { - var enumValue = value as Enum; - - return enumValue?.GetDescriptionFromEnumValue() ?? Avalonia.AvaloniaProperty.UnsetValue; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureInfo) - { - return value; - } - } -} diff --git a/src/OutGridView.Gui/Converters/IValueToStringConverter.cs b/src/OutGridView.Gui/Converters/IValueToStringConverter.cs deleted file mode 100644 index a244a83..0000000 --- a/src/OutGridView.Gui/Converters/IValueToStringConverter.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Avalonia.Data.Converters; -using OutGridView.Application.Models; -using System.Globalization; -using OutGridView.Models; - -namespace OutGridView.Application.Converters -{ - public class IValueToStringConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo) - { - IValue stringValue = value as IValue; - return stringValue.DisplayValue; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureInfo) - { - return value; - } - } -} diff --git a/src/OutGridView.Gui/FodyWeavers.xml b/src/OutGridView.Gui/FodyWeavers.xml deleted file mode 100644 index 63fc148..0000000 --- a/src/OutGridView.Gui/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/OutGridView.Gui/FodyWeavers.xsd b/src/OutGridView.Gui/FodyWeavers.xsd deleted file mode 100644 index f3ac476..0000000 --- a/src/OutGridView.Gui/FodyWeavers.xsd +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. - - - - - A comma-separated list of error codes that can be safely ignored in assembly verification. - - - - - 'false' to turn off automatic generation of the XML Schema file. - - - - - \ No newline at end of file diff --git a/src/OutGridView.Gui/Models/Column.cs b/src/OutGridView.Gui/Models/Column.cs deleted file mode 100644 index dad5662..0000000 --- a/src/OutGridView.Gui/Models/Column.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Reflection; -using ReactiveUI.Fody.Helpers; -using ReactiveUI; -using System; -using System.Linq; -using OutGridView.Models; -using System.Collections.Generic; - -namespace OutGridView.Application.Models -{ - public class Column : ReactiveObject - { - public DataTableColumn DataColumn { get; set; } - [Reactive] public Boolean IsVisible { get; set; } - public Column(DataTableColumn dataColumn) - { - DataColumn = dataColumn; - IsVisible = true; - } - } -} diff --git a/src/OutGridView.Gui/Models/Filter.cs b/src/OutGridView.Gui/Models/Filter.cs deleted file mode 100644 index f67857c..0000000 --- a/src/OutGridView.Gui/Models/Filter.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Reflection; -using ReactiveUI.Fody.Helpers; -using ReactiveUI; -using System; -using System.Linq; -using System.Collections.Generic; -using System.Reactive.Linq; -using OutGridView.Application.Services.FilterOperators; -using OutGridView.Models; - -namespace OutGridView.Application.Models -{ - public class Filter : ReactiveObject - { - //List of Operators used in View - public static IEnumerable Operators { get; } = Enum.GetValues(typeof(StringFilterOperator)).Cast(); - public DataTableColumn DataColumn { get; set; } - [Reactive] public StringFilterOperator SelectedOperator { get; set; } - - public IStringFilterOperator SelectedFilterOperator { [ObservableAsProperty] get; } - [Reactive] public string Value { get; set; } - public Filter(DataTableColumn dataColumn) - { - this.WhenAnyValue(x => x.SelectedOperator, x => x.Value, (op, value) => FilterOperatorLookup.CreateFilterOperatorRule(op, value)) - .ToPropertyEx(this, x => x.SelectedFilterOperator, FilterOperatorLookup.CreateFilterOperatorRule(SelectedOperator, Value)); - - DataColumn = dataColumn; - SelectedOperator = StringFilterOperator.Contains; - Value = string.Empty; - } - } -} diff --git a/src/OutGridView.Gui/Models/FilterGroup.cs b/src/OutGridView.Gui/Models/FilterGroup.cs deleted file mode 100644 index 9bbf287..0000000 --- a/src/OutGridView.Gui/Models/FilterGroup.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Reactive; -using System.Reactive.Disposables; -using System.Reactive.Linq; -using System.Reflection; -using DynamicData.Binding; -using ReactiveUI; -using OutGridView.Models; - - -namespace OutGridView.Application.Models -{ - public class FilterGroup : ReactiveObject - { - public FilterGroup(DataTableColumn dataColumn, IEnumerable filters) - { - this.DataColumn = dataColumn; - this.Filters = filters; - } - public IEnumerable Filters { get; } - public DataTableColumn DataColumn { get; } - } -} diff --git a/src/OutGridView.Gui/Models/NumericFilter.cs b/src/OutGridView.Gui/Models/NumericFilter.cs deleted file mode 100644 index 6c90bdb..0000000 --- a/src/OutGridView.Gui/Models/NumericFilter.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -namespace OutGridView.Application.Models -{ - public class NumericFilter - { - - } -} diff --git a/src/OutGridView.Gui/Models/NumericFilterOperator.cs b/src/OutGridView.Gui/Models/NumericFilterOperator.cs deleted file mode 100644 index 3a455ac..0000000 --- a/src/OutGridView.Gui/Models/NumericFilterOperator.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -namespace OutGridView.Application.Models -{ - public enum NumericFilterOperator - { - - } -} diff --git a/src/OutGridView.Gui/Models/StringFilterOperator.cs b/src/OutGridView.Gui/Models/StringFilterOperator.cs deleted file mode 100644 index 9e8d8c3..0000000 --- a/src/OutGridView.Gui/Models/StringFilterOperator.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ComponentModel; - -namespace OutGridView.Application.Models -{ - public enum StringFilterOperator - { - [Description("Contains")] - Contains, - [Description("Equals")] - Equals, - [Description("Doesn't Contain")] - NotContains, - [Description("Starts With")] - StartsWith, - [Description("Doesn't Equal")] - NotEquals, - [Description("Ends With")] - EndwsWith, - [Description("Is Not Empty")] - NotIsEmpty, - [Description("Is Empty")] - IsEmpty - } -} diff --git a/src/OutGridView.Gui/OutGridView.Gui.csproj b/src/OutGridView.Gui/OutGridView.Gui.csproj deleted file mode 100644 index a275569..0000000 --- a/src/OutGridView.Gui/OutGridView.Gui.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - Exe - net6.0 - - - - - %(Filename) - - - Designer - - - - - - - - - - - - - - - - - - - diff --git a/src/OutGridView.Gui/Program.cs b/src/OutGridView.Gui/Program.cs deleted file mode 100644 index e0ac658..0000000 --- a/src/OutGridView.Gui/Program.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Avalonia; -using Avalonia.Logging.Serilog; -using OutGridView.Application.ViewModels; -using OutGridView.Application.Views; -using OutGridView.Application.Services; -using System.Collections.Generic; -using OutGridView.Models; -using System.Text; -using System.Diagnostics; - -//Used to run the module directly from Dotnet -namespace OutGridView.Application -{ - public class Program - { - // Initialization code. Don't use any Avalonia, third-party APIs or any - // SynchronizationContext-reliant code before AppMain is called: things aren't initialized - // yet and stuff might break. - [STAThread] - public static void Main(string[] args) - { - var base64ApplicationData = Console.ReadLine(); - - var applicationData = Serializers.ObjectFromJson(base64ApplicationData); - - AvaloniaAppRunner.RunApp(applicationData); - - var passThruIndexes = AvaloniaAppRunner.GetPassThruIndexes(); - - Console.WriteLine(Serializers.ObjectToJson(passThruIndexes)); - - } - } -} diff --git a/src/OutGridView.Gui/Services/EnumExtensions.cs b/src/OutGridView.Gui/Services/EnumExtensions.cs deleted file mode 100644 index 5661dab..0000000 --- a/src/OutGridView.Gui/Services/EnumExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.ComponentModel; -using System.Linq; -using System.Reflection; - -public static class EnumExtensions -{ - public static string GetDescriptionFromEnumValue(this Enum value) - { - return value - .GetType() - .GetMember(value.ToString()) - .FirstOrDefault() - ?.GetCustomAttribute() - ?.Description - ?? value.ToString(); - } - - -} diff --git a/src/OutGridView.Gui/Services/FilterBuilder.cs b/src/OutGridView.Gui/Services/FilterBuilder.cs deleted file mode 100644 index 1b7a264..0000000 --- a/src/OutGridView.Gui/Services/FilterBuilder.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text.RegularExpressions; -using OutGridView.Application.Models; -using OutGridView.Application.Services.FilterOperators; -using System.Collections.ObjectModel; -using DynamicData; -using OutGridView.Models; - - -namespace OutGridView.Application.Services -{ - static class FilterBuilder - { - public static Func BuildFilter(string searchText, IObservableList filters) - { - var filterQuery = BuildFilterQuery(filters); - var quickSearchFilter = BuildQuickSearchFilter(searchText); - return dataList => filterQuery(dataList) && quickSearchFilter(dataList); - } - public static Func BuildFilterQuery(IObservableList filterGroups) - { - - return dataList => filterGroups.Items.All(filterGroup => - { - return filterGroup.Filters.Any(f => - { - //Empty filter is always valid (if it requires a value) - if (f.SelectedFilterOperator.HasValue && String.IsNullOrEmpty(f.Value)) - { - return true; - } - var rule = f.SelectedFilterOperator; - var value = dataList.Values[f.DataColumn.ToString()]; - return rule.Execute(value?.DisplayValue ?? String.Empty); - }); - }); - } - - public static Func BuildQuickSearchFilter(string searchText) - { - List tokens = ParseSearchText(searchText); - - if (string.IsNullOrEmpty(searchText)) - { - return dataList => true; - } - - //For all terms at least-one property matches - return dataList => tokens.All(t => - { - return dataList.Values.Any(data => - { - //Quick Search is NOT case-sensitive - return data.Value != null && data.Value.DisplayValue.ToLowerInvariant().Contains(t.ToLowerInvariant()); - }); - }); - } - public static string TokenPattern = @"[^\s""']+|""([^""]*)""|'([^']*)'"; - //Seperates words by spaces unless they are quoted - public static List ParseSearchText(string searchText) - { - RegexOptions options = RegexOptions.Multiline; - - List stringMatches = new List(); - - foreach (Match m in Regex.Matches(searchText, TokenPattern, options)) - { - string token; - - if (m.Groups[1].Value != String.Empty) - { - token = m.Groups[1].Value; - } - else if (m.Groups[2].Value != String.Empty) - { - token = m.Groups[2].Value; - } - else - { - token = m.Value; - } - - stringMatches.Add(token); - } - return stringMatches; - } - } -} - - diff --git a/src/OutGridView.Gui/Services/FilterOperators/ContainsOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/ContainsOperator.cs deleted file mode 100644 index 5ce2297..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/ContainsOperator.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; - -namespace OutGridView.Application.Services.FilterOperators -{ - public class ContainsOperator : IStringFilterOperator - { - public bool HasValue { get; } = true; - public string Value { get; set; } - public bool Execute(string input) - { - return input.Contains(Value, StringComparison.CurrentCultureIgnoreCase); - } - public string GetPowerShellString() - { - var val = PowerShellCodeGenerator.EscapePowerShellLikeString(Value); - return $"-Like \'*{val}*\'"; - } - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/EndsWithOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/EndsWithOperator.cs deleted file mode 100644 index 8c82996..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/EndsWithOperator.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Globalization; -namespace OutGridView.Application.Services.FilterOperators -{ - public class EndsWithOperator : IStringFilterOperator - { - public bool HasValue { get; } = true; - public string Value { get; set; } - public bool Execute(string input) - { - return input.EndsWith(Value, true, CultureInfo.CurrentCulture); - } - public string GetPowerShellString() - { - var val = PowerShellCodeGenerator.EscapePowerShellLikeString(Value); - return $"-Like \'*{val}\'"; - } - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/EqualsOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/EqualsOperator.cs deleted file mode 100644 index 8f205c6..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/EqualsOperator.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; - -namespace OutGridView.Application.Services.FilterOperators -{ - public class EqualsOperator : IStringFilterOperator - { - public bool HasValue { get; } = true; - public string Value { get; set; } - public bool Execute(string input) - { - return input.Equals(Value, StringComparison.CurrentCultureIgnoreCase); - } - public string GetPowerShellString() - { - return $"-EQ \'{Value}\'"; - } - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/FilterOperatorLookup.cs b/src/OutGridView.Gui/Services/FilterOperators/FilterOperatorLookup.cs deleted file mode 100644 index e50be65..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/FilterOperatorLookup.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using OutGridView.Application.Models; -using System; - -namespace OutGridView.Application.Services.FilterOperators -{ - public static class FilterOperatorLookup - { - public static IStringFilterOperator CreateFilterOperatorRule(StringFilterOperator filterOp, string value) - { - switch (filterOp) - { - case StringFilterOperator.Contains: - return new ContainsOperator { Value = value }; - case StringFilterOperator.Equals: - return new EqualsOperator { Value = value }; - case StringFilterOperator.NotContains: - return new NotContainsOperator { Value = value }; - case StringFilterOperator.StartsWith: - return new StartsWithOperator { Value = value }; - case StringFilterOperator.EndwsWith: - return new EndsWithOperator { Value = value }; - case StringFilterOperator.NotEquals: - return new NotEqualsOperator { Value = value }; - case StringFilterOperator.NotIsEmpty: - return new NotIsEmptyOperator { Value = value }; - case StringFilterOperator.IsEmpty: - return new IsEmptyOperator(); - default: - throw new Exception("Invalid Rule"); - } - } - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/IFilterOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/IFilterOperator.cs deleted file mode 100644 index 622ee1d..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/IFilterOperator.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace OutGridView.Application.Services.FilterOperators -{ - public interface IFilterOperator - { - bool HasValue { get; } - bool Execute(string input); - string GetPowerShellString(); - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/IStringFilterOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/IStringFilterOperator.cs deleted file mode 100644 index 73ab59b..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/IStringFilterOperator.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace OutGridView.Application.Services.FilterOperators -{ - public interface IStringFilterOperator : IFilterOperator - { - string Value { get; } - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/IsEmptyOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/IsEmptyOperator.cs deleted file mode 100644 index 0be928e..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/IsEmptyOperator.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -namespace OutGridView.Application.Services.FilterOperators -{ - public class IsEmptyOperator : IStringFilterOperator - { - public bool HasValue { get; } = false; - public string Value { get; set; } - public bool Execute(string input) - { - return String.IsNullOrWhiteSpace(input); - } - public string GetPowerShellString() - { - return $"-EQ \'\'"; - } - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/NotContainsOperators.cs b/src/OutGridView.Gui/Services/FilterOperators/NotContainsOperators.cs deleted file mode 100644 index 8892630..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/NotContainsOperators.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -namespace OutGridView.Application.Services.FilterOperators -{ - public class NotContainsOperator : IStringFilterOperator - { - public bool HasValue { get; } = true; - public string Value { get; set; } - public bool Execute(string input) - { - return !input.Contains(Value, StringComparison.CurrentCultureIgnoreCase); - } - public string GetPowerShellString() - { - return $"-NotContains \'{Value}\'"; - } - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/NotEqualsOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/NotEqualsOperator.cs deleted file mode 100644 index 08bf1a1..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/NotEqualsOperator.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -namespace OutGridView.Application.Services.FilterOperators -{ - public class NotEqualsOperator : IStringFilterOperator - { - public bool HasValue { get; } = true; - public string Value { get; set; } - public bool Execute(string input) - { - return !input.Equals(Value, StringComparison.CurrentCultureIgnoreCase); - } - public string GetPowerShellString() - { - return $"-NE \'{Value}\'"; - } - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/NotIsEmptyOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/NotIsEmptyOperator.cs deleted file mode 100644 index 8d548e9..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/NotIsEmptyOperator.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -namespace OutGridView.Application.Services.FilterOperators -{ - public class NotIsEmptyOperator : IStringFilterOperator - { - public bool HasValue { get; } = false; - public string Value { get; set; } - public bool Execute(string input) - { - return !String.IsNullOrEmpty(Value); - } - public string GetPowerShellString() - { - return $"-NE \'\'"; - } - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/NumericFilterOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/NumericFilterOperator.cs deleted file mode 100644 index c9b3ac5..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/NumericFilterOperator.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace OutGridView.Application.Services.FilterOperators -{ - public abstract class NumericFilterOperator : IFilterOperator - { - public bool HasValue { get; } = true; - public decimal Value { get; set; } - public abstract bool Execute(string input); - public abstract string GetPowerShellString(); - } -} diff --git a/src/OutGridView.Gui/Services/FilterOperators/StartsWithOperator.cs b/src/OutGridView.Gui/Services/FilterOperators/StartsWithOperator.cs deleted file mode 100644 index 79c2953..0000000 --- a/src/OutGridView.Gui/Services/FilterOperators/StartsWithOperator.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Globalization; -namespace OutGridView.Application.Services.FilterOperators -{ - public class StartsWithOperator : IStringFilterOperator - { - public bool HasValue { get; } = true; - public string Value { get; set; } - public bool Execute(string input) - { - return input.StartsWith(Value, true, CultureInfo.CurrentCulture); - } - public string GetPowerShellString() - { - var val = PowerShellCodeGenerator.EscapePowerShellLikeString(Value); - return $"-Like \'{val}*\'"; - } - } -} diff --git a/src/OutGridView.Gui/Services/ModalService.cs b/src/OutGridView.Gui/Services/ModalService.cs deleted file mode 100644 index 04b56dd..0000000 --- a/src/OutGridView.Gui/Services/ModalService.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using OutGridView.Application.ViewModels; -using OutGridView.Application.Views; -using Avalonia; - -namespace OutGridView.Application.Services -{ - public class ModalService - { - public void ShowCodeModal(string filterString) - { - var showCodeModal = new ShowCodeModal - { - DataContext = new ShowCodeModalViewModel(filterString) - }; - - showCodeModal.ShowDialog(Avalonia.Application.Current.MainWindow); - } - } -} diff --git a/src/OutGridView.Gui/Services/PowerShellCodeGenerator.cs b/src/OutGridView.Gui/Services/PowerShellCodeGenerator.cs deleted file mode 100644 index e005a9c..0000000 --- a/src/OutGridView.Gui/Services/PowerShellCodeGenerator.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using OutGridView.Application.Models; -using System; -using System.Linq; -using System.Collections.Generic; - -namespace OutGridView.Application.Services -{ - public static class PowerShellCodeGenerator - { - public static string GetPowershellForFilterGroups(IEnumerable filterGroups) - { - var whereObjectClauses = filterGroups.Select(filterGroup => - { - var operatorStrings = filterGroup.Filters.Select(filter => - { - var powerShellString = filter.SelectedFilterOperator.GetPowerShellString(); - return $" {filterGroup.DataColumn.PropertyScriptAccessor} {powerShellString} "; - }); - - var operatorString = String.Join("-or", operatorStrings); - return $"Where-Object {{ {operatorString} }}"; - }); - - //New line join for readability - return String.Join(" |" + System.Environment.NewLine, whereObjectClauses); - } - public static string EscapePowerShellLikeString(string str) - { - //PowerShell like has special escape characters - var charsToEscape = new List { "[", "]", "?", "*" }; - foreach (var character in charsToEscape) - { - str = str.Replace(character, "`" + character); - } - return str; - } - } -} diff --git a/src/OutGridView.Gui/Style.xaml b/src/OutGridView.Gui/Style.xaml deleted file mode 100644 index b0eae67..0000000 --- a/src/OutGridView.Gui/Style.xaml +++ /dev/null @@ -1,58 +0,0 @@ - diff --git a/src/OutGridView.Gui/ViewLocator.cs b/src/OutGridView.Gui/ViewLocator.cs deleted file mode 100644 index f83d089..0000000 --- a/src/OutGridView.Gui/ViewLocator.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System; -using Avalonia.Controls; -using Avalonia.Controls.Templates; -using OutGridView.Application.ViewModels; - -namespace OutGridView -{ - public class ViewLocator : IDataTemplate - { - public bool SupportsRecycling => false; - - public IControl Build(object data) - { - var name = data.GetType().FullName.Replace("ViewModel", "View"); - var type = Type.GetType(name); - - if (type != null) - { - return (Control)Activator.CreateInstance(type); - } - else - { - return new TextBlock { Text = "Not Found: " + name }; - } - } - - public bool Match(object data) - { - return data is ViewModelBase; - } - } -} diff --git a/src/OutGridView.Gui/ViewModels/DataGridViewModel.cs b/src/OutGridView.Gui/ViewModels/DataGridViewModel.cs deleted file mode 100644 index 7af8dd6..0000000 --- a/src/OutGridView.Gui/ViewModels/DataGridViewModel.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using OutGridView.Application.Models; -using ReactiveUI; -using System.Collections.ObjectModel; -using System.Reactive.Disposables; -using Avalonia.Controls; -using DynamicData; -using Avalonia; -using OutGridView.Application.Views; -using DynamicData.ReactiveUI; -using System.Reactive.Linq; -using System.Reflection; -using System.Linq; -using System.Reactive; -using System.Threading.Tasks; -using OutGridView.Models; - - -namespace OutGridView.Application.ViewModels -{ - public class DataGridViewModel : ViewModelBase - { - private ReadOnlyObservableCollection _viewObjects; - public ReadOnlyObservableCollection ViewObjects => _viewObjects; - - public SourceList Columns { get; } = new SourceList(); - private ReadOnlyObservableCollection _columnSelect; - public ReadOnlyObservableCollection ColumnSelect => _columnSelect; - public DataGridSelectionMode SelectionMode { get; set; } - public List SelectedRows { get; set; } - public DataGridViewModel(List dataColumns, IObservableList data, OutputModeOption outputMode) - { - var columns = dataColumns.Select(x => new Column(x)); - - Columns.AddRange(columns); - - SelectionMode = OutputModeToSelectionMode(outputMode); - - this.WhenActivated((CompositeDisposable disposables) => - { - Columns.Connect() - .AutoRefresh() - .ObserveOn(RxApp.MainThreadScheduler) - .Bind(out _columnSelect) - .Subscribe(); - - data.Connect() - .Bind(out _viewObjects) - .Subscribe(); - }); - } - - public DataGridSelectionMode OutputModeToSelectionMode(OutputModeOption outputModeOption) - { - switch (outputModeOption) - { - case OutputModeOption.None: - return DataGridSelectionMode.Extended; - case OutputModeOption.Single: - return DataGridSelectionMode.Single; - case OutputModeOption.Multiple: - return DataGridSelectionMode.Extended; - default: - return DataGridSelectionMode.Extended; - } - } - } -} diff --git a/src/OutGridView.Gui/ViewModels/FilterQueryBuilderViewModel.cs b/src/OutGridView.Gui/ViewModels/FilterQueryBuilderViewModel.cs deleted file mode 100644 index d250195..0000000 --- a/src/OutGridView.Gui/ViewModels/FilterQueryBuilderViewModel.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using OutGridView.Application.Models; -using ReactiveUI; -using DynamicData; -using DynamicData.ReactiveUI; -using System.Linq; -using System.Reactive; -using System.Reactive.Disposables; -using System.Reactive.Linq; -using System.Collections.ObjectModel; -using ReactiveUI.Fody.Helpers; -using DynamicData.Aggregation; -using OutGridView.Models; -using OutGridView.Application.Services; - -namespace OutGridView.Application.ViewModels -{ - public class FilterQueryBuilderViewModel : ViewModelBase - { - private SourceList DataColumnOptions = new SourceList(); - - private ReadOnlyObservableCollection _visibleDataColumnOptions; - public ReadOnlyObservableCollection VisibleDataColumnOptions => _visibleDataColumnOptions; - [Reactive] public DataTableColumn SelectedAddColumn { get; set; } - public SourceList Filters { get; } = new SourceList(); - public IObservableList FiltersByDataColumn { get; set; } - private ReadOnlyObservableCollection _filtersByDataColumnView; - public ReadOnlyObservableCollection FiltersByDataColumnView => _filtersByDataColumnView; - public ReactiveCommand AddFilterCommand { get; } - public ReactiveCommand RemoveFilterCommand { get; } - public ReactiveCommand ClearFiltersCommand { get; } - public ReactiveCommand ShowCodeCommand { get; } - public Boolean IsColumnSelectVisible { [ObservableAsProperty] get; } - - //Placeholder hack for combo box - private DataTableColumn placeholderColumn = new DataTableColumn("Add Column Filter", "System.Int32"); - - public FilterQueryBuilderViewModel(IObservableList dataColumns) - { - - DataColumnOptions.Add(placeholderColumn); - DataColumnOptions.AddRange(dataColumns.Items); - - SelectedAddColumn = placeholderColumn; - - AddFilterCommand = ReactiveCommand.Create(AddFilter); - RemoveFilterCommand = ReactiveCommand.Create(RemoveFilter); - ClearFiltersCommand = ReactiveCommand.Create(ClearFilters); - ShowCodeCommand = ReactiveCommand.Create(ShowCode); - - - this.WhenActivated((CompositeDisposable disposables) => - { - var filterGroups = Filters.Connect() - .GroupWithImmutableState(x => x.DataColumn) - .Transform(grouping => new FilterGroup(grouping.Key, grouping.Items)); - - FiltersByDataColumn = Filters.Connect() - .AutoRefresh() - .GroupWithImmutableState(x => x.DataColumn) - .Transform(grouping => new FilterGroup(grouping.Key, grouping.Items)) - .ObserveOn(RxApp.MainThreadScheduler) - .DisposeMany() - .AsObservableList(); - - filterGroups - .AutoRefresh() - .ObserveOn(RxApp.MainThreadScheduler) - .Bind(out _filtersByDataColumnView) - .DisposeMany() - .Subscribe(); - - var activeDataColumns = Filters.Connect() - .Transform(x => x.DataColumn) - .DistinctValues(x => x) - .DisposeMany() - .ObserveOn(RxApp.MainThreadScheduler); - - var dataColumnOptions = DataColumnOptions.Connect() - .Except(activeDataColumns) - .Publish(); - - dataColumnOptions - .Bind(out _visibleDataColumnOptions) - .Subscribe(); - - dataColumnOptions - .Count() - .Select(x => x > 1) - .ToPropertyEx(this, x => x.IsColumnSelectVisible); - - dataColumnOptions.Connect(); - }); - } - - private void AddFilter(DataTableColumn dataColumn) - { - if (dataColumn == placeholderColumn) return; - - Filters.Add(new Filter(dataColumn)); - SelectedAddColumn = placeholderColumn; - } - - private void RemoveFilter(Filter filter) - { - Filters.Remove(filter); - } - - private void ShowCode() - { - var filterGroupList = _filtersByDataColumnView.ToList(); - var filterString = PowerShellCodeGenerator.GetPowershellForFilterGroups(filterGroupList); - - //TODO: Inject service - var modalService = new ModalService(); - - modalService.ShowCodeModal(filterString); - } - - private void ClearFilters() - { - Filters.Clear(); - } - } -} diff --git a/src/OutGridView.Gui/ViewModels/MainWindowViewModel.cs b/src/OutGridView.Gui/ViewModels/MainWindowViewModel.cs deleted file mode 100644 index ce7a1aa..0000000 --- a/src/OutGridView.Gui/ViewModels/MainWindowViewModel.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using OutGridView.Application.Services; -using ReactiveUI; -using System.Reactive.Disposables; -using ReactiveUI.Fody.Helpers; -using DynamicData; -using System.Linq; -using System.Reactive.Linq; -using System.Reactive; -using Avalonia.Controls; -using OutGridView.Models; -using System.Collections.Generic; - -namespace OutGridView.Application.ViewModels -{ - public class MainWindowViewModel : ViewModelBase - { - private readonly DataTable dataTable; - [Reactive] public FilterQueryBuilderViewModel FilterQueryBuilder { get; set; } - [Reactive] public DataGridViewModel DataGridView { get; set; } - [Reactive] public string SearchText { get; set; } = String.Empty; - public bool IsPassThruEnabled { get; } - public string Title { get; } - public ReactiveCommand PassThruOkCommand { get; } - public ReactiveCommand PassThruCancelCommand { get; } - private readonly OutputModeOption outputMode; - public List OutputObjectIndexes { get; set; } = new List(); - public MainWindowViewModel(ApplicationData applicationData) - { - IsPassThruEnabled = applicationData.PassThru; - Title = applicationData.Title; - outputMode = applicationData.OutputMode; - dataTable = applicationData.DataTable; - - PassThruOkCommand = ReactiveCommand.Create(OnPassThruOk); - PassThruCancelCommand = ReactiveCommand.Create(OnPassThruCancel); - - - var observableColumns = new SourceList(); - - observableColumns.AddRange(dataTable.DataColumns); - - var observableData = new SourceList(); - - observableData.AddRange(dataTable.Data); - this.WhenActivated((CompositeDisposable disposables) => - { - - - - FilterQueryBuilder = new FilterQueryBuilderViewModel(observableColumns); - - var filterData = Observable.Merge(this.WhenAnyValue(x => x.SearchText).Select(_ => Unit.Default), - FilterQueryBuilder.FiltersByDataColumn.Connect().AutoRefresh().Select(_ => Unit.Default)); - - var filterPredicate = filterData.Select(x => FilterBuilder.BuildFilter(SearchText, FilterQueryBuilder.FiltersByDataColumn)); - - var filteredObjects = observableData.Connect() - .Filter(filterPredicate) - .AsObservableList(); - - DataGridView = new DataGridViewModel(dataTable.DataColumns, filteredObjects, outputMode); - }); - } - - public void OnPassThruOk(Window window) - { - OutputObjectIndexes = DataGridView.SelectedRows.Select(x => x.OriginalObjectIndex).ToList(); - - CloseProgam(window); - } - - public void OnPassThruCancel(Window window) - { - CloseProgam(window); - } - - public void CloseProgam(Window window) - { - window.Close(); - } - } -} diff --git a/src/OutGridView.Gui/ViewModels/ShowCodeModalViewModel.cs b/src/OutGridView.Gui/ViewModels/ShowCodeModalViewModel.cs deleted file mode 100644 index f89c6d9..0000000 --- a/src/OutGridView.Gui/ViewModels/ShowCodeModalViewModel.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using OutGridView.Application.Models; -using ReactiveUI; -using DynamicData; -using DynamicData.ReactiveUI; -using System.Linq; -using System.Reactive; -using Avalonia; -using System.Reactive.Disposables; - -namespace OutGridView.Application.ViewModels -{ - public class ShowCodeModalViewModel : ViewModelBase - { - public string FilterScript { get; set; } - public ReactiveCommand CopyToClipboardCommand { get; } - - private readonly string _placholderText = "Add a filter to see generated code"; - - public ShowCodeModalViewModel(string filterScript) - { - if (String.IsNullOrEmpty(filterScript)) - { - FilterScript = _placholderText; - } - else - { - FilterScript = filterScript; - } - - CopyToClipboardCommand = ReactiveCommand.Create(CopyToClipboard); - - this.WhenActivated((CompositeDisposable disposables) => - { - }); - } - - private void CopyToClipboard() - { - Avalonia.Application.Current.Clipboard.SetTextAsync(FilterScript); - } - } -} diff --git a/src/OutGridView.Gui/ViewModels/ViewModelBase.cs b/src/OutGridView.Gui/ViewModels/ViewModelBase.cs deleted file mode 100644 index c79c8d1..0000000 --- a/src/OutGridView.Gui/ViewModels/ViewModelBase.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reactive.Disposables; -using ReactiveUI; - -namespace OutGridView.Application.ViewModels -{ - public partial class ViewModelBase : ReactiveObject, ISupportsActivation - { - public ViewModelActivator Activator { get; } - - public ViewModelBase() - { - Activator = new ViewModelActivator(); - this.WhenActivated((CompositeDisposable disposables) => { }); - } - } -} diff --git a/src/OutGridView.Gui/Views/DataGridView.xaml b/src/OutGridView.Gui/Views/DataGridView.xaml deleted file mode 100644 index 38e203b..0000000 --- a/src/OutGridView.Gui/Views/DataGridView.xaml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - Columns - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/OutGridView.Gui/Views/DataGridView.xaml.cs b/src/OutGridView.Gui/Views/DataGridView.xaml.cs deleted file mode 100644 index 954fef4..0000000 --- a/src/OutGridView.Gui/Views/DataGridView.xaml.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Avalonia; -using Avalonia.Controls; -using Avalonia.Markup.Xaml; -using OutGridView.Application.ViewModels; -using OutGridView.Application.Models; -using System.Reactive.Disposables; -using ReactiveUI; -using System.Collections.Generic; -using System.Linq; -using OutGridView.Application.Converters; -using DynamicData; -using Avalonia.Data; -using OutGridView.Models; -using System; - -namespace OutGridView.Application.Views -{ - public class DataGridView : ReactiveUserControl - { - - public DataGrid DataGridTable => this.FindControl("DataGridTable"); - - public DataGridView() - { - InitializeComponent(); - } - - private void InitializeComponent() - { - this.WhenActivated((CompositeDisposable disposables) => - { - DataGridTable.WhenAnyValue(x => x.SelectedItem, x => x.SelectedItems, (x, y) => y.OfType().ToList()) - .BindTo(this, x => x.ViewModel.SelectedRows) - .DisposeWith(disposables); - - //Bind the data columns directly on the DataGrid - ViewModel.Columns.Connect() - .AutoRefresh() - .Filter(x => x.IsVisible) - .Transform(ColumnToDataGridTextColumn) - .Bind(out var columns) - .DisposeMany() - .Subscribe(x => - { - DataGridTable.Columns.Clear(); //TODO incremental? - DataGridTable.Columns.AddRange(columns); - }); - }); - - AvaloniaXamlLoader.Load(this); - } - private DataGridTextColumn ColumnToDataGridTextColumn(Column column) - { - var binding = new Binding - { - Path = "Values[" + column.DataColumn.ToString() + "]", - Mode = BindingMode.OneTime - }; - - binding.Converter = new IValueToStringConverter(); - - return new DataGridTextColumn() - { - Binding = binding, - Header = column.DataColumn.Label, - CanUserReorder = true, - CanUserSort = true, - }; - } - } - -} diff --git a/src/OutGridView.Gui/Views/FilterQueryBuilderView.xaml b/src/OutGridView.Gui/Views/FilterQueryBuilderView.xaml deleted file mode 100644 index b4f7625..0000000 --- a/src/OutGridView.Gui/Views/FilterQueryBuilderView.xaml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/OutGridView.Gui/Views/MainWindow.xaml.cs b/src/OutGridView.Gui/Views/MainWindow.xaml.cs deleted file mode 100644 index c3ab87c..0000000 --- a/src/OutGridView.Gui/Views/MainWindow.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Avalonia; -using Avalonia.Controls; -using Avalonia.Markup.Xaml; -using OutGridView.Application.ViewModels; -using System.Reactive.Disposables; -using ReactiveUI; - - -namespace OutGridView.Application.Views -{ - public class MainWindow : ReactiveWindow - { - public MainWindow() - { - InitializeComponent(); - } - - private void InitializeComponent() - { - this.WhenActivated((CompositeDisposable disposables) => - { - }); - AvaloniaXamlLoader.Load(this); - } - } -} diff --git a/src/OutGridView.Gui/Views/ShowCodeModalView.xaml b/src/OutGridView.Gui/Views/ShowCodeModalView.xaml deleted file mode 100644 index ff50b8d..0000000 --- a/src/OutGridView.Gui/Views/ShowCodeModalView.xaml +++ /dev/null @@ -1,11 +0,0 @@ - - - -