From 1faa402dce3629da5b99c995306d83081187d346 Mon Sep 17 00:00:00 2001 From: feyris-tan <4116042+feyris-tan@users.noreply.github.com> Date: Tue, 1 Jul 2025 18:20:58 +0200 Subject: [PATCH] An Object Storage can now be configured in the ImGui. --- .../MinioObjectStorageFactory.cs | 2 + .../skyscraper5.Data.Minio.csproj | 2 +- .../PostgresqlDataStoreFactory.cs | 2 +- ...orage.cs => ConfigureDataStorageWindow.cs} | 2 +- .../Forms/ConfigureObjectStorageWindow.cs | 191 ++++++++++++++++++ .../Forms/ConfigureTunerFactoryWindow.cs | 3 +- GUIs/skyscraper8.UI.ImGui/Program.cs | 67 ++++-- 7 files changed, 250 insertions(+), 19 deletions(-) rename GUIs/skyscraper8.UI.ImGui/Forms/{ConfigureStorage.cs => ConfigureDataStorageWindow.cs} (99%) create mode 100644 GUIs/skyscraper8.UI.ImGui/Forms/ConfigureObjectStorageWindow.cs diff --git a/BlobStorages/skyscraper5.Data.Minio/MinioObjectStorageFactory.cs b/BlobStorages/skyscraper5.Data.Minio/MinioObjectStorageFactory.cs index 2a6d0b2..0ea12a7 100644 --- a/BlobStorages/skyscraper5.Data.Minio/MinioObjectStorageFactory.cs +++ b/BlobStorages/skyscraper5.Data.Minio/MinioObjectStorageFactory.cs @@ -35,6 +35,8 @@ namespace skyscraper5.Data.Minio .WithCredentials(AccessKey, SecretKey) .WithSSL(Secure).Build(); BucketExistsArgs bucketExistsArgs = new BucketExistsArgs().WithBucket(Bucket); + Task bucketExistsAsync = mc.BucketExistsAsync(bucketExistsArgs); + bucketExistsAsync.Wait(); bool bucketExists = mc.BucketExistsAsync(bucketExistsArgs).Result; if (!bucketExists) { diff --git a/BlobStorages/skyscraper5.Data.Minio/skyscraper5.Data.Minio.csproj b/BlobStorages/skyscraper5.Data.Minio/skyscraper5.Data.Minio.csproj index f208679..e66e7c2 100644 --- a/BlobStorages/skyscraper5.Data.Minio/skyscraper5.Data.Minio.csproj +++ b/BlobStorages/skyscraper5.Data.Minio/skyscraper5.Data.Minio.csproj @@ -5,7 +5,7 @@ - + diff --git a/DataTableStorages/skyscraper5.Data.PostgreSql/PostgresqlDataStoreFactory.cs b/DataTableStorages/skyscraper5.Data.PostgreSql/PostgresqlDataStoreFactory.cs index 1d498d6..8f72377 100644 --- a/DataTableStorages/skyscraper5.Data.PostgreSql/PostgresqlDataStoreFactory.cs +++ b/DataTableStorages/skyscraper5.Data.PostgreSql/PostgresqlDataStoreFactory.cs @@ -30,7 +30,7 @@ namespace skyscraper5.Data.PostgreSql public DataStorage CreateDataStorage() { - logger.Log(PluginLogLevel.Info, "Connecting to PostgreSQL & MinIO"); + logger.Log(PluginLogLevel.Info, "Connecting to postgres://{3}@{0}:{1}/{2}",Host,Port,Database,Username); NpgsqlConnectionStringBuilder ncsb = new NpgsqlConnectionStringBuilder(); ncsb.Database = Database; ncsb.ApplicationName = "skyscraper5"; diff --git a/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureStorage.cs b/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureDataStorageWindow.cs similarity index 99% rename from GUIs/skyscraper8.UI.ImGui/Forms/ConfigureStorage.cs rename to GUIs/skyscraper8.UI.ImGui/Forms/ConfigureDataStorageWindow.cs index 5d96a5d..06c7f29 100644 --- a/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureStorage.cs +++ b/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureDataStorageWindow.cs @@ -25,7 +25,7 @@ namespace SDL2Demo.Forms Ini = ini; StorageFactories = storageFactories; IsOpen = true; - storageId = ini.ReadValue("startup", "storage", 0); + storageId = ini.ReadValue("startup", "dataStorage", 0); settings = new List(); FactoryNames = new Dictionary(); connectionManager = StorageConnectionManager.GetInstance(); diff --git a/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureObjectStorageWindow.cs b/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureObjectStorageWindow.cs new file mode 100644 index 0000000..a848e50 --- /dev/null +++ b/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureObjectStorageWindow.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using ImGuiNET; +using skyscraper5.Skyscraper; +using skyscraper8.Skyscraper.Scraper.Storage; + +namespace SDL2Demo.Forms +{ + internal class ConfigureObjectStorageWindow : IRenderable + { + public Ini Ini { get; } + public ReadOnlyCollection> StorageFactories { get; } + private Dictionary FactoryNames; + private Dictionary TempGuids; + private StorageConnectionManager connectionManager; + + public ConfigureObjectStorageWindow(Ini ini, ReadOnlyCollection> storageFactories) + { + Ini = ini; + StorageFactories = storageFactories; + IsOpen = true; + storageId = ini.ReadValue("startup", "objectStorage", 0); + settings = new List(); + FactoryNames = new Dictionary(); + connectionManager = StorageConnectionManager.GetInstance(); + TempGuids = new Dictionary(); + + + foreach (KeyValuePair keyValuePair in storageFactories) + { + FactoryNames.Add(keyValuePair.Key, connectionManager.GetName(keyValuePair.Value)); + TempGuids.Add(keyValuePair.Key, Guid.NewGuid()); + PropertyInfo[] propertyInfos = keyValuePair.Value.GetType().GetProperties(); + foreach (PropertyInfo propertyInfo in propertyInfos) + { + ConfigureDataStorageWindow.Setting s = new ConfigureDataStorageWindow.Setting(); + s.IniKey = keyValuePair.Key; + s.SettingName = propertyInfo.Name; + s.SettingControlUuid = Guid.NewGuid().ToString(); + switch (propertyInfo.PropertyType.Name) + { + case nameof(String): + s.SettingMode = 1; + s.StringValue = ini.ReadValue(String.Format("objectStorage{0}", s.IniKey), s.SettingName, ""); + break; + case nameof(Boolean): + s.SettingMode = 2; + s.BooleanValue = ini.ReadValue(String.Format("objectStorage{0}", s.IniKey), s.SettingName, false); + break; + case nameof(UInt16): + s.SettingMode = 3; + s.UshortValue = (ushort)ini.ReadValue(String.Format("objectStorage{0}", s.IniKey), s.SettingName, ushort.MinValue); + break; + default: + throw new NotImplementedException(propertyInfo.PropertyType.Name); + } + + settings.Add(s); + } + } + } + + public bool IsOpen; + private bool HasChanges; + private int storageId; + private List settings; + public bool RequireRestart; + + private void Save() + { + Ini.WriteValue("startup", "objectStorage", storageId); + foreach (ConfigureDataStorageWindow.Setting setting in settings) + { + switch (setting.SettingMode) + { + case 1: + Ini.WriteValue(String.Format("objectStorage{0}", setting.IniKey), setting.SettingName, setting.StringValue); + break; + case 2: + Ini.WriteValue(String.Format("objectStorage{0}", setting.IniKey), setting.SettingName, setting.BooleanValue); + break; + case 3: + Ini.WriteValue(String.Format("objectStorage{0}", setting.IniKey), setting.SettingName, setting.UshortValue); + break; + default: + throw new NotImplementedException(String.Format("Setting mode {0}", setting.SettingMode)); + } + } + + Ini.Export(new FileInfo("skyscraper5.ini")); + + if (HasChanges) + RequireRestart = true; + HasChanges = false; + + } + + private bool CanApply() + { + foreach (ConfigureDataStorageWindow.Setting setting in settings.Where(x => x.IniKey == storageId)) + { + if (!setting.Validate()) + { + return false; + } + } + + return true; + } + + public void Render() + { + ImGuiWindowFlags flags = ImGuiWindowFlags.None; + if (HasChanges) + flags |= ImGuiWindowFlags.UnsavedDocument; + + ImGui.Begin("Configure ScraperStorage", ref IsOpen, flags); + + foreach (KeyValuePair keyValuePair in StorageFactories) + { + if (ImGui.RadioButton(FactoryNames[keyValuePair.Key], ref storageId, keyValuePair.Key)) + { + HasChanges = true; + } + + ImGui.BeginTable(TempGuids[keyValuePair.Key].ToString(), 2); + + foreach (ConfigureDataStorageWindow.Setting setting in settings.Where(x => x.IniKey == keyValuePair.Key)) + { + ImGui.TableNextRow(); + ImGui.TableSetColumnIndex(0); + ImGui.Text(setting.SettingName); + ImGui.TableSetColumnIndex(1); + ImGui.PushID(setting.SettingControlUuid); + switch (setting.SettingMode) + { + case 1: + if (ImGui.InputText("", ref setting.StringValue, 255)) + HasChanges = true; + break; + case 2: + if (ImGui.Checkbox("", ref setting.BooleanValue)) + HasChanges = true; + break; + case 3: + if (setting.UshortValue < ushort.MinValue) + setting.UshortValue = ushort.MinValue; + if (setting.UshortValue > ushort.MaxValue) + setting.UshortValue = ushort.MaxValue; + if (ImGui.InputInt("", ref setting.UshortValue)) + HasChanges = true; + break; + default: + throw new NotImplementedException(String.Format("Setting mode {0}", setting.SettingMode)); + } + } + ImGui.PopID(); + ImGui.EndTable(); + } + + bool canApply = CanApply(); + ImGui.BeginDisabled(!canApply); + if (ImGui.Button("OK")) + { + Save(); + IsOpen = false; + } + ImGui.EndDisabled(); + + ImGui.SameLine(); + if (ImGui.Button("Cancel")) + { + IsOpen = false; + } + + ImGui.SameLine(); + ImGui.BeginDisabled(!canApply); + if (ImGui.Button("Apply")) + { + Save(); + } + ImGui.EndDisabled(); + ImGui.End(); + } + } +} diff --git a/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureTunerFactoryWindow.cs b/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureTunerFactoryWindow.cs index a261bb6..67887cf 100644 --- a/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureTunerFactoryWindow.cs +++ b/GUIs/skyscraper8.UI.ImGui/Forms/ConfigureTunerFactoryWindow.cs @@ -167,10 +167,11 @@ namespace SDL2Demo.Forms } ImGui.PopID(); } - ImGui.EndTable(); } + ImGui.Separator(); + bool canApply = CanApply(); ImGui.BeginDisabled(!canApply); if (ImGui.Button("OK")) diff --git a/GUIs/skyscraper8.UI.ImGui/Program.cs b/GUIs/skyscraper8.UI.ImGui/Program.cs index 64fc4d3..6f7071d 100644 --- a/GUIs/skyscraper8.UI.ImGui/Program.cs +++ b/GUIs/skyscraper8.UI.ImGui/Program.cs @@ -200,7 +200,8 @@ namespace SkyscraperUI private List messageWindows; private AboutWindow aboutWindow; - private ConfigureDataStorageWindow configureStorageWindow; + private ConfigureDataStorageWindow configureDataStorageWindow; + private ConfigureObjectStorageWindow configureObjectStorageWindow; private SatellitesConfigurationWindow satellitesConfigurationWindow; private List satellitePositions; private List lnbTypes; @@ -522,11 +523,6 @@ namespace SkyscraperUI configureDishTypesWindow = new ConfigureDishTypes(dataStorage, dishTypes); } - if (ImGui.MenuItem("Configure Data Storage", configureStorageWindow == null)) - { - configureStorageWindow = new ConfigureDataStorageWindow(ini, dataStorageFactories); - } - if (ImGui.MenuItem("Configure GPS Receiver", configureGpsWindow == null)) { configureGpsWindow = new ConfigureGpsWindow(ini); @@ -536,8 +532,18 @@ namespace SkyscraperUI { satellitesConfigurationWindow = new SatellitesConfigurationWindow(dataStorage); } - - ImGui.EndMenu(); + + if (ImGui.MenuItem("Configure Data Storage", configureDataStorageWindow == null)) + { + configureDataStorageWindow = new ConfigureDataStorageWindow(ini, dataStorageFactories); + } + + if (ImGui.MenuItem("Configure Object Storage", configureObjectStorageWindow == null)) + { + configureObjectStorageWindow = new ConfigureObjectStorageWindow(ini, objectStorageFactories); + } + + ImGui.EndMenu(); } if (ImGui.BeginMenu("Data")) @@ -620,12 +626,12 @@ namespace SkyscraperUI if (showDemoWindow) ImGui.ShowDemoWindow(); - if (configureStorageWindow != null) + if (configureDataStorageWindow != null) { - configureStorageWindow.Render(); - if (!configureStorageWindow.IsOpen) + configureDataStorageWindow.Render(); + if (!configureDataStorageWindow.IsOpen) { - if (configureStorageWindow.RequireRestart) + if (configureDataStorageWindow.RequireRestart) { MessageWindow mw = new MessageWindow( "To apply the storage configuration, skyscraper5 will need to restart. Press the okay button to exit the application."); @@ -633,11 +639,28 @@ namespace SkyscraperUI messageWindows.Add(mw); } - configureStorageWindow = null; + configureDataStorageWindow = null; } } - if (configureGpsWindow != null) + if (configureObjectStorageWindow != null) + { + configureObjectStorageWindow.Render(); + if (!configureObjectStorageWindow.IsOpen) + { + if (configureObjectStorageWindow.RequireRestart) + { + MessageWindow mw = new MessageWindow( + "To apply the storage configuration, skyscraper5 will need to restart. Press the okay button to exit the application."); + mw.OnClose = () => quit = true; + messageWindows.Add(mw); + } + + configureObjectStorageWindow = null; + } + } + + if (configureGpsWindow != null) { configureGpsWindow.Render(); if (!configureGpsWindow.IsOpen) @@ -877,7 +900,21 @@ namespace SkyscraperUI { uiBlockingWindow.Text = "It isn't."; uiBlockingWindow.Line2 = "Creating object storage..."; - objectStorage = objectStorageFactory.CreateObjectStorage(); + try + { + objectStorage = objectStorageFactory.CreateObjectStorage(); + } + catch (Exception e) + { + string objectStorageName = connectionManager.GetName(objectStorageFactory); + localLogger.Log(PluginLogLevel.Error, "Failed to start the object storage factory: {0}", e.Message); + string rant = String.Format("Could not load {1}.\nThe following went wrong:\n\n{0}\n\n", e.Message, objectStorageName); + messageWindows.Add(new MessageWindow(rant)); + blockUi = false; + showMainMenu = true; + return; + } + }