Profile settings
This commit is contained in:
@ -1,9 +1,9 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.13.35919.96 d17.13
|
||||
VisualStudioVersion = 17.13.35919.96
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "proxmox-spice-launcher", "src\proxmox-spice-launcher\proxmox-spice-launcher\proxmox-spice-launcher.csproj", "{9A4EC4BE-8920-461F-8653-A9650A68B727}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "proxmox-spice-launcher", "src\proxmox-spice-launcher\proxmox-spice-launcher.csproj", "{8F3740FC-DC36-1459-2ECB-B04F0BBA4ED8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -11,10 +11,10 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9A4EC4BE-8920-461F-8653-A9650A68B727}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9A4EC4BE-8920-461F-8653-A9650A68B727}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9A4EC4BE-8920-461F-8653-A9650A68B727}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9A4EC4BE-8920-461F-8653-A9650A68B727}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8F3740FC-DC36-1459-2ECB-B04F0BBA4ED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8F3740FC-DC36-1459-2ECB-B04F0BBA4ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8F3740FC-DC36-1459-2ECB-B04F0BBA4ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8F3740FC-DC36-1459-2ECB-B04F0BBA4ED8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -0,0 +1,16 @@
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Proxmox.SpiceLauncher.Extensions;
|
||||
internal static class ObservableCollectionExtensions
|
||||
{
|
||||
public static ObservableCollection<T> Sort<T>(this ObservableCollection<T> collection, Comparison<T> comparison)
|
||||
{
|
||||
var sortableList = new List<T>(collection);
|
||||
sortableList.Sort(comparison);
|
||||
for (int i = 0; i < sortableList.Count; i++)
|
||||
{
|
||||
collection.Move(collection.IndexOf(sortableList[i]), i);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
xmlns:local="clr-namespace:Proxmox.SpiceLauncher"
|
||||
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
|
||||
mc:Ignorable="d"
|
||||
Title="Proxmox Spice Launcher" Height="391" Width="350" ResizeMode="NoResize"
|
||||
Title="Proxmox Spice Launcher" Height="391" Width="539" ResizeMode="NoResize"
|
||||
Initialized="MetroWindow_Initialized" Closing="MetroWindow_Closing" SizeToContent="Height"
|
||||
Icon="pack://application:,,,/Proxmox.SpiceLauncher.png">
|
||||
<mah:MetroWindow.Resources>
|
||||
@ -29,18 +29,24 @@
|
||||
</mah:MetroWindow.RightWindowCommands>
|
||||
|
||||
<Grid>
|
||||
<StackPanel Margin="10,10,10,10">
|
||||
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal">
|
||||
<mah:MetroHeader Header="Profile">
|
||||
<ComboBox x:Name="ComboProfiles" SelectionChanged="ComboProfiles_OnSelectionChanged" />
|
||||
<StackPanel>
|
||||
<StackPanel Grid.IsSharedSizeScope="True" Margin="10,10,10,10">
|
||||
<mah:MetroHeader Header="Profile" HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid>
|
||||
<ComboBox x:Name="ComboProfiles" SelectionChanged="ComboProfiles_OnSelectionChanged" Margin="0,0,100,0" />
|
||||
<Button x:Name="ButtonConnect" Content="Connect" Click="ButtonConnect_Click"
|
||||
HorizontalAlignment="Right" Width="90" />
|
||||
</Grid>
|
||||
</mah:MetroHeader>
|
||||
<Button x:Name="ButtonConnect" Content="Connect" Click="ButtonConnect_Click" Margin="5,0,0,0" />
|
||||
</StackPanel>
|
||||
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal">
|
||||
<mah:MetroHeader Header="VM">
|
||||
<ComboBox x:Name="ComboVms" />
|
||||
<mah:MetroHeader Header="VM" HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid>
|
||||
<ComboBox x:Name="ComboVms" Margin="0,0,100,0" />
|
||||
<Button x:Name="ButtonSpice" Content="Spice" Click="ButtonSpice_Click"
|
||||
HorizontalAlignment="Right" IsEnabled="False" Width="90" />
|
||||
</Grid>
|
||||
</mah:MetroHeader>
|
||||
<Button x:Name="ButtonSpice" Content="Spice" Click="ButtonSpice_Click" IsEnabled="False" Margin="5,0,0,0" RenderTransformOrigin="4.474,0.491" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
@ -1,4 +1,5 @@
|
||||
using System.ComponentModel;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
@ -19,7 +20,7 @@ namespace Proxmox.SpiceLauncher;
|
||||
public partial class MainWindow
|
||||
{
|
||||
private PveClient? _client;
|
||||
private List<Settings> _settings;
|
||||
private ObservableCollection<Settings> _settings;
|
||||
private List<VmWrapper> _vms = new();
|
||||
private readonly string _settingsFile;
|
||||
|
||||
@ -30,22 +31,13 @@ public partial class MainWindow
|
||||
}
|
||||
private async void MetroWindow_Initialized(object sender, EventArgs e)
|
||||
{
|
||||
List<Settings>? settings = null;
|
||||
ObservableCollection<Settings>? settings = null;
|
||||
if (File.Exists(_settingsFile))
|
||||
{
|
||||
await using var f = File.OpenRead(_settingsFile);
|
||||
settings = await JsonSerializer.DeserializeAsync<List<Settings>>(f);
|
||||
}
|
||||
if (settings == null || settings.Count == 0)
|
||||
{
|
||||
settings =
|
||||
[
|
||||
new Settings()
|
||||
{
|
||||
Server = "192.168.0.190"
|
||||
}
|
||||
];
|
||||
settings = await JsonSerializer.DeserializeAsync<ObservableCollection<Settings>>(f);
|
||||
}
|
||||
settings ??= [];
|
||||
_settings = settings;
|
||||
ComboProfiles.ItemsSource = _settings;
|
||||
ComboProfiles.SelectedIndex = 0;
|
||||
@ -54,13 +46,12 @@ public partial class MainWindow
|
||||
|
||||
private void ButtonSettings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
/*
|
||||
var settings = new SettingsWindow
|
||||
{
|
||||
Owner = this
|
||||
Owner = this,
|
||||
Settings = _settings
|
||||
};
|
||||
settings.ShowDialog();
|
||||
*/
|
||||
}
|
||||
|
||||
private async Task DoEvent(Func<Task> e)
|
||||
@ -105,6 +96,12 @@ public partial class MainWindow
|
||||
throw new Exception("Login failed");
|
||||
}
|
||||
|
||||
var nodes = await _client.GetHostAndIpAsync();
|
||||
var current = nodes.FirstOrDefault(x => x.Value == _client.Host);
|
||||
if (current.Key != null)
|
||||
{
|
||||
settings.Name = current.Key;
|
||||
}
|
||||
var vms = await _client.GetVmsAsync();
|
||||
foreach (var vm in vms)
|
||||
{
|
50
src/proxmox-spice-launcher/Models/Settings.cs
Normal file
50
src/proxmox-spice-launcher/Models/Settings.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Proxmox.SpiceLauncher.Models;
|
||||
|
||||
public class Settings{
|
||||
private string? _password;
|
||||
private string? _passwordEnc;
|
||||
public string? Server { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Username { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string? Password
|
||||
{
|
||||
get => _password;
|
||||
set
|
||||
{
|
||||
_password = value;
|
||||
_passwordEnc = value != null ? DPApi.EncryptStringToBase64(value) : null;
|
||||
}
|
||||
}
|
||||
|
||||
public string? PasswordEnc
|
||||
{
|
||||
get => _passwordEnc;
|
||||
set
|
||||
{
|
||||
_passwordEnc = value;
|
||||
try
|
||||
{
|
||||
_password = value == null ? null : DPApi.DecryptStringFromBase64(value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_password = null;
|
||||
_passwordEnc = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var server = (Username != null ? $"{Username}@" : null) + Server ?? "Unknown";
|
||||
if (Name != null)
|
||||
{
|
||||
return $"{Name} ({server})";
|
||||
}
|
||||
return server;
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
26
src/proxmox-spice-launcher/SettingsWindow.xaml
Normal file
26
src/proxmox-spice-launcher/SettingsWindow.xaml
Normal file
@ -0,0 +1,26 @@
|
||||
<mah:MetroWindow x:Class="Proxmox.SpiceLauncher.SettingsWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
|
||||
xmlns:local="clr-namespace:Proxmox.SpiceLauncher"
|
||||
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
|
||||
mc:Ignorable="d"
|
||||
Title="Settings" Height="368" Width="625" ResizeMode="NoResize" WindowStartupLocation="CenterOwner"
|
||||
SizeToContent="Height">
|
||||
<mah:MetroWindow.Resources>
|
||||
<Style BasedOn="{StaticResource MahApps.Styles.MetroHeader.Horizontal}" TargetType="mah:MetroHeader" />
|
||||
</mah:MetroWindow.Resources>
|
||||
<Grid>
|
||||
<StackPanel Margin="10,10,10,10">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,0,10">
|
||||
<Button x:Name="ButtonAdd" Content="{iconPacks:FontAwesome Kind=PlusSolid}" Click="ButtonAdd_Click"
|
||||
Margin="0,0,5,0" />
|
||||
<Button x:Name="ButtonDelete" Content="{iconPacks:FontAwesome Kind=MinusSolid}" Click="ButtonDelete_Click"
|
||||
Margin="0,0,5,0" />
|
||||
</StackPanel>
|
||||
<ListBox Name="ListSettings"></ListBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</mah:MetroWindow>
|
50
src/proxmox-spice-launcher/SettingsWindow.xaml.cs
Normal file
50
src/proxmox-spice-launcher/SettingsWindow.xaml.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using Proxmox.SpiceLauncher.Models;
|
||||
using System.Windows;
|
||||
using MahApps.Metro.Controls.Dialogs;
|
||||
using Proxmox.SpiceLauncher.Extensions;
|
||||
|
||||
namespace Proxmox.SpiceLauncher;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for SettingsWindow.xaml
|
||||
/// </summary>
|
||||
public partial class SettingsWindow
|
||||
{
|
||||
private ObservableCollection<Settings> _settings;
|
||||
|
||||
public SettingsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ObservableCollection<Settings> Settings
|
||||
{
|
||||
get => _settings;
|
||||
set
|
||||
{
|
||||
_settings = value;
|
||||
ListSettings.ItemsSource = _settings;
|
||||
}
|
||||
}
|
||||
|
||||
private async void ButtonAdd_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var server = await this.ShowInputAsync("Proxmox Server", "Proxmox server IP or Hostname");
|
||||
if (string.IsNullOrEmpty(server))
|
||||
return;
|
||||
Settings.Add(new Settings
|
||||
{
|
||||
Server = server
|
||||
});
|
||||
Settings.Sort((a, b) => string.Compare(a.ToString(), b.ToString(), StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
private void ButtonDelete_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ListSettings.SelectedItem is Settings settings)
|
||||
{
|
||||
_settings.Remove(settings);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Proxmox.SpiceLauncher.Models;
|
||||
|
||||
class Settings
|
||||
{
|
||||
private string _password;
|
||||
private string _passwordEnc;
|
||||
public string Server { get; set; }
|
||||
public string Username { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string Password
|
||||
{
|
||||
get => _password;
|
||||
set
|
||||
{
|
||||
_password = value;
|
||||
_passwordEnc = DPApi.EncryptStringToBase64(value);
|
||||
}
|
||||
}
|
||||
|
||||
public string PasswordEnc
|
||||
{
|
||||
get => _passwordEnc;
|
||||
set
|
||||
{
|
||||
_passwordEnc = value;
|
||||
_password = DPApi.DecryptStringFromBase64(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Server;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user