diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
commit | c04dcc2e7d834218ef2d4194331e383402495ae1 (patch) | |
tree | 7333e38d10d75386e60f336b80c2443c1166031d /xbmc/addons/gui/GUIDialogAddonSettings.cpp | |
parent | Initial commit. (diff) | |
download | kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip |
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/addons/gui/GUIDialogAddonSettings.cpp')
-rw-r--r-- | xbmc/addons/gui/GUIDialogAddonSettings.cpp | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/xbmc/addons/gui/GUIDialogAddonSettings.cpp b/xbmc/addons/gui/GUIDialogAddonSettings.cpp new file mode 100644 index 0000000..bc794d4 --- /dev/null +++ b/xbmc/addons/gui/GUIDialogAddonSettings.cpp @@ -0,0 +1,484 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIDialogAddonSettings.h" + +#include "FileItem.h" +#include "GUIPassword.h" +#include "GUIUserMessages.h" +#include "ServiceBroker.h" +#include "addons/AddonManager.h" +#include "addons/settings/AddonSettings.h" +#include "dialogs/GUIDialogSelect.h" +#include "dialogs/GUIDialogYesNo.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/WindowIDs.h" +#include "input/Key.h" +#include "messaging/helpers/DialogOKHelper.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "settings/lib/SettingSection.h" +#include "settings/lib/SettingsManager.h" +#include "utils/StringUtils.h" +#include "utils/Variant.h" +#include "utils/log.h" +#include "view/ViewStateSettings.h" + +#define CONTROL_BTN_LEVELS 20 + +using namespace ADDON; +using namespace KODI::MESSAGING; + +CGUIDialogAddonSettings::CGUIDialogAddonSettings() + : CGUIDialogSettingsManagerBase(WINDOW_DIALOG_ADDON_SETTINGS, "DialogAddonSettings.xml") +{ +} + +bool CGUIDialogAddonSettings::OnMessage(CGUIMessage& message) +{ + switch (message.GetMessage()) + { + case GUI_MSG_CLICKED: + { + if (message.GetSenderId() == CONTROL_SETTINGS_CUSTOM_BUTTON) + { + OnResetSettings(); + return true; + } + break; + } + + case GUI_MSG_SETTING_UPDATED: + { + const std::string& settingId = message.GetStringParam(0); + const std::string& settingValue = message.GetStringParam(1); + const ADDON::AddonInstanceId instanceId = message.GetParam1(); + + if (instanceId != m_instanceId) + { + CLog::Log(LOGERROR, + "CGUIDialogAddonSettings::{}: Set value \"{}\" from add-on \"{}\" called with " + "invalid instance id (given: {}, needed: {})", + __func__, m_addon->ID(), settingId, instanceId, m_instanceId); + break; + } + + std::shared_ptr<CSetting> setting = GetSettingsManager()->GetSetting(settingId); + if (setting != nullptr) + { + setting->FromString(settingValue); + return true; + } + break; + } + + default: + break; + } + + return CGUIDialogSettingsManagerBase::OnMessage(message); +} + +bool CGUIDialogAddonSettings::OnAction(const CAction& action) +{ + switch (action.GetID()) + { + case ACTION_SETTINGS_LEVEL_CHANGE: + { + // Test if we can access the new level + if (!g_passwordManager.CheckSettingLevelLock( + CViewStateSettings::GetInstance().GetNextSettingLevel(), true)) + return false; + + CViewStateSettings::GetInstance().CycleSettingLevel(); + CServiceBroker::GetSettingsComponent()->GetSettings()->Save(); + + // try to keep the current position + std::string oldCategory; + if (m_iCategory >= 0 && m_iCategory < static_cast<int>(m_categories.size())) + oldCategory = m_categories[m_iCategory]->GetId(); + + SET_CONTROL_LABEL(CONTROL_BTN_LEVELS, + 10036 + + static_cast<int>(CViewStateSettings::GetInstance().GetSettingLevel())); + // only re-create the categories, the settings will be created later + SetupControls(false); + + m_iCategory = 0; + // try to find the category that was previously selected + if (!oldCategory.empty()) + { + for (int i = 0; i < static_cast<int>(m_categories.size()); i++) + { + if (m_categories[i]->GetId() == oldCategory) + { + m_iCategory = i; + break; + } + } + } + + CreateSettings(); + return true; + } + + default: + break; + } + + return CGUIDialogSettingsManagerBase::OnAction(action); +} + +bool CGUIDialogAddonSettings::ShowForAddon(const ADDON::AddonPtr& addon, + bool saveToDisk /* = true */) +{ + if (!addon) + { + CLog::LogF(LOGERROR, "No addon given!"); + return false; + } + + if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER)) + return false; + + if (addon->SupportsInstanceSettings()) + return ShowForMultipleInstances(addon, saveToDisk); + else + return ShowForSingleInstance(addon, saveToDisk); +} + +bool CGUIDialogAddonSettings::ShowForSingleInstance( + const ADDON::AddonPtr& addon, + bool saveToDisk, + ADDON::AddonInstanceId instanceId /* = ADDON::ADDON_SETTINGS_ID */) +{ + if (!addon->HasSettings(instanceId)) + { + // addon does not support settings, inform user + HELPERS::ShowOKDialogText(CVariant{24000}, CVariant{24030}); + return false; + } + + // Create the dialog + CGUIDialogAddonSettings* dialog = + CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogAddonSettings>( + WINDOW_DIALOG_ADDON_SETTINGS); + if (!dialog) + { + CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_ADDON_SETTINGS instance!"); + return false; + } + + dialog->m_addon = addon; + dialog->m_instanceId = instanceId; + dialog->m_saveToDisk = saveToDisk; + + dialog->Open(); + + if (!dialog->IsConfirmed()) + { + addon->ReloadSettings(instanceId); + return false; + } + + if (saveToDisk) + addon->SaveSettings(instanceId); + + return true; +} + +bool CGUIDialogAddonSettings::ShowForMultipleInstances(const ADDON::AddonPtr& addon, + bool saveToDisk) +{ + CGUIDialogSelect* dialog = + CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>( + WINDOW_DIALOG_SELECT); + if (!dialog) + { + CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_SELECT instance!"); + return false; + } + + int lastSelected = -1; + while (true) + { + std::vector<ADDON::AddonInstanceId> ids = addon->GetKnownInstanceIds(); + std::sort(ids.begin(), ids.end(), [](const auto& a, const auto& b) { return a < b; }); + + dialog->Reset(); + dialog->SetHeading(10012); // Add-on configurations and settings + dialog->SetUseDetails(false); + + CFileItemList itemsInstances; + ADDON::AddonInstanceId highestId = 0; + for (const auto& id : ids) + { + std::string name; + addon->GetSettingString(ADDON_SETTING_INSTANCE_NAME_VALUE, name, id); + if (name.empty()) + name = g_localizeStrings.Get(13205); // Unknown + + bool enabled = false; + addon->GetSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE, enabled, id); + + const std::string label = StringUtils::Format( + g_localizeStrings.Get(10020), name, + g_localizeStrings.Get(enabled ? 305 : 13106)); // Edit "config name" [enabled state] + + const CFileItemPtr item = std::make_shared<CFileItem>(label); + item->SetProperty("id", id); + item->SetProperty("name", name); + itemsInstances.Add(item); + + if (id > highestId) + highestId = id; + } + + CFileItemList itemsGeneral; + + const ADDON::AddonInstanceId addInstanceId = highestId + 1; + const ADDON::AddonInstanceId removeInstanceId = highestId + 2; + + CFileItemPtr item = + std::make_shared<CFileItem>(g_localizeStrings.Get(10014)); // Add add-on configuration + item->SetProperty("id", addInstanceId); + itemsGeneral.Add(item); + + if (ids.size() > 1) // Forbid removal of last instance + { + item = + std::make_shared<CFileItem>(g_localizeStrings.Get(10015)); // Remove add-on configuration + item->SetProperty("id", removeInstanceId); + itemsGeneral.Add(item); + } + + if (addon->HasSettings(ADDON_SETTINGS_ID)) + { + item = std::make_shared<CFileItem>(g_localizeStrings.Get(10013)); // Edit Add-on settings + item->SetProperty("id", ADDON_SETTINGS_ID); + itemsGeneral.Add(item); + } + + for (auto& it : itemsGeneral) + dialog->Add(*it); + + for (auto& it : itemsInstances) + dialog->Add(*it); + + // Select last selected item, first instance config item or first item + if (lastSelected >= 0) + dialog->SetSelected(lastSelected); + else + dialog->SetSelected(itemsInstances.Size() > 0 ? itemsGeneral.Size() : 0); + + dialog->Open(); + + if (dialog->IsButtonPressed() || !dialog->IsConfirmed()) + break; + + lastSelected = dialog->GetSelectedItem(); + + item = dialog->GetSelectedFileItem(); + ADDON::AddonInstanceId instanceId = item->GetProperty("id").asInteger(); + + if (instanceId == addInstanceId) + { + instanceId = highestId + 1; + + addon->GetSettings(instanceId); + addon->UpdateSettingString(ADDON_SETTING_INSTANCE_NAME_VALUE, "", instanceId); + addon->UpdateSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE, true, instanceId); + addon->SaveSettings(instanceId); + + if (ShowForSingleInstance(addon, saveToDisk, instanceId)) + { + CServiceBroker::GetAddonMgr().PublishInstanceAdded(addon->ID(), instanceId); + } + else + { + // Remove instance settings if not succeeded (e.g. dialog cancelled) + addon->DeleteInstanceSettings(instanceId); + } + } + else if (instanceId == removeInstanceId) + { + dialog->Reset(); + dialog->SetHeading(10010); // Select add-on configuration to remove + dialog->SetUseDetails(false); + + for (auto& it : itemsInstances) + { + CFileItem item(*it); + item.SetLabel((*it).GetProperty("name").asString()); + dialog->Add(item); + } + + dialog->SetSelected(0); + dialog->Open(); + + if (!dialog->IsButtonPressed() && dialog->IsConfirmed()) + { + item = dialog->GetSelectedFileItem(); + const std::string label = StringUtils::Format( + g_localizeStrings.Get(10019), + item->GetProperty("name") + .asString()); // Do you want to remove the add-on configuration "config name"? + + if (CGUIDialogYesNo::ShowAndGetInput(10009, // Confirm add-on configuration removal + label)) + { + instanceId = item->GetProperty("id").asInteger(); + addon->DeleteInstanceSettings(instanceId); + CServiceBroker::GetAddonMgr().PublishInstanceRemoved(addon->ID(), instanceId); + } + } + } + else + { + // edit instance settings or edit addon settings selected; open settings dialog + + bool enabled = false; + addon->GetSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE, enabled, instanceId); + + if (ShowForSingleInstance(addon, saveToDisk, instanceId) && instanceId != ADDON_SETTINGS_ID) + { + // Publish new/removed instance configuration and start the use of new instance + bool enabledNow = false; + addon->GetSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE, enabledNow, instanceId); + if (enabled != enabledNow) + { + if (enabledNow) + CServiceBroker::GetAddonMgr().PublishInstanceAdded(addon->ID(), instanceId); + else + CServiceBroker::GetAddonMgr().PublishInstanceRemoved(addon->ID(), instanceId); + } + } + } + + // refresh selection dialog content... + + } // while (true) + + return true; +} + +void CGUIDialogAddonSettings::SaveAndClose() +{ + if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER)) + return; + + // get the dialog + CGUIDialogAddonSettings* dialog = + CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogAddonSettings>( + WINDOW_DIALOG_ADDON_SETTINGS); + if (dialog == nullptr || !dialog->IsActive()) + return; + + // check if we need to save the settings + if (dialog->m_saveToDisk && dialog->m_addon != nullptr) + dialog->m_addon->SaveSettings(dialog->m_instanceId); + + // close the dialog + dialog->Close(); +} + +std::string CGUIDialogAddonSettings::GetCurrentAddonID() const +{ + if (m_addon == nullptr) + return ""; + + return m_addon->ID(); +} + +void CGUIDialogAddonSettings::SetupView() +{ + if (m_addon == nullptr || m_addon->GetSettings(m_instanceId) == nullptr) + return; + + auto settings = m_addon->GetSettings(m_instanceId); + if (!settings->IsLoaded()) + return; + + CGUIDialogSettingsManagerBase::SetupView(); + + // set addon id as window property + SetProperty("Addon.ID", m_addon->ID()); + + // set heading + SetHeading(StringUtils::Format("$LOCALIZE[10004] - {}", + m_addon->Name())); // "Settings - AddonName" + + // set control labels + SET_CONTROL_LABEL(CONTROL_SETTINGS_OKAY_BUTTON, 186); + SET_CONTROL_LABEL(CONTROL_SETTINGS_CANCEL_BUTTON, 222); + SET_CONTROL_LABEL(CONTROL_SETTINGS_CUSTOM_BUTTON, 409); + SET_CONTROL_LABEL(CONTROL_BTN_LEVELS, + 10036 + static_cast<int>(CViewStateSettings::GetInstance().GetSettingLevel())); +} + +std::string CGUIDialogAddonSettings::GetLocalizedString(uint32_t labelId) const +{ + std::string label = g_localizeStrings.GetAddonString(m_addon->ID(), labelId); + if (!label.empty()) + return label; + + return CGUIDialogSettingsManagerBase::GetLocalizedString(labelId); +} + +std::string CGUIDialogAddonSettings::GetSettingsLabel(const std::shared_ptr<ISetting>& setting) +{ + if (setting == nullptr) + return ""; + + std::string label = GetLocalizedString(setting->GetLabel()); + if (!label.empty()) + return label; + + // try the addon settings + label = m_addon->GetSettings(m_instanceId)->GetSettingLabel(setting->GetLabel()); + if (!label.empty()) + return label; + + return CGUIDialogSettingsManagerBase::GetSettingsLabel(setting); +} + +int CGUIDialogAddonSettings::GetSettingLevel() const +{ + return static_cast<int>(CViewStateSettings::GetInstance().GetSettingLevel()); +} + +std::shared_ptr<CSettingSection> CGUIDialogAddonSettings::GetSection() +{ + const auto settingsManager = GetSettingsManager(); + if (settingsManager == nullptr) + return nullptr; + + const auto sections = settingsManager->GetSections(); + if (!sections.empty()) + return sections.front(); + + return nullptr; +} + +CSettingsManager* CGUIDialogAddonSettings::GetSettingsManager() const +{ + if (m_addon == nullptr || m_addon->GetSettings(m_instanceId) == nullptr) + return nullptr; + + return m_addon->GetSettings(m_instanceId)->GetSettingsManager(); +} + +void CGUIDialogAddonSettings::OnSettingAction(const std::shared_ptr<const CSetting>& setting) +{ + if (m_addon == nullptr || m_addon->GetSettings(m_instanceId) == nullptr) + return; + + m_addon->GetSettings(m_instanceId)->OnSettingAction(setting); +} |