2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "GUIDialogAddonSettings.h"
12 #include "FileItemList.h"
13 #include "GUIPassword.h"
14 #include "GUIUserMessages.h"
15 #include "ServiceBroker.h"
16 #include "addons/AddonManager.h"
17 #include "addons/addoninfo/AddonType.h"
18 #include "addons/settings/AddonSettings.h"
19 #include "dialogs/GUIDialogSelect.h"
20 #include "dialogs/GUIDialogYesNo.h"
21 #include "guilib/GUIComponent.h"
22 #include "guilib/GUIWindowManager.h"
23 #include "guilib/LocalizeStrings.h"
24 #include "guilib/WindowIDs.h"
25 #include "input/actions/Action.h"
26 #include "input/actions/ActionIDs.h"
27 #include "messaging/helpers/DialogOKHelper.h"
28 #include "settings/Settings.h"
29 #include "settings/SettingsComponent.h"
30 #include "settings/lib/SettingSection.h"
31 #include "settings/lib/SettingsManager.h"
32 #include "utils/StringUtils.h"
33 #include "utils/Variant.h"
34 #include "utils/log.h"
35 #include "view/ViewStateSettings.h"
37 #define CONTROL_BTN_LEVELS 20
39 using namespace ADDON
;
40 using namespace KODI::MESSAGING
;
42 CGUIDialogAddonSettings::CGUIDialogAddonSettings()
43 : CGUIDialogSettingsManagerBase(WINDOW_DIALOG_ADDON_SETTINGS
, "DialogAddonSettings.xml")
47 bool CGUIDialogAddonSettings::OnMessage(CGUIMessage
& message
)
49 switch (message
.GetMessage())
53 if (message
.GetSenderId() == CONTROL_SETTINGS_CUSTOM_BUTTON
)
61 case GUI_MSG_SETTING_UPDATED
:
63 const std::string
& settingId
= message
.GetStringParam(0);
64 const std::string
& settingValue
= message
.GetStringParam(1);
65 const ADDON::AddonInstanceId instanceId
= message
.GetParam1();
67 if (instanceId
!= m_instanceId
)
70 "CGUIDialogAddonSettings::{}: Set value \"{}\" from add-on \"{}\" called with "
71 "invalid instance id (given: {}, needed: {})",
72 __func__
, m_addon
->ID(), settingId
, instanceId
, m_instanceId
);
76 std::shared_ptr
<CSetting
> setting
= GetSettingsManager()->GetSetting(settingId
);
77 if (setting
!= nullptr)
79 setting
->FromString(settingValue
);
89 return CGUIDialogSettingsManagerBase::OnMessage(message
);
92 bool CGUIDialogAddonSettings::OnAction(const CAction
& action
)
94 switch (action
.GetID())
96 case ACTION_SETTINGS_LEVEL_CHANGE
:
98 // Test if we can access the new level
99 if (!g_passwordManager
.CheckSettingLevelLock(
100 CViewStateSettings::GetInstance().GetNextSettingLevel(), true))
103 CViewStateSettings::GetInstance().CycleSettingLevel();
104 CServiceBroker::GetSettingsComponent()->GetSettings()->Save();
106 // try to keep the current position
107 std::string oldCategory
;
108 if (m_iCategory
>= 0 && m_iCategory
< static_cast<int>(m_categories
.size()))
109 oldCategory
= m_categories
[m_iCategory
]->GetId();
111 SET_CONTROL_LABEL(CONTROL_BTN_LEVELS
,
113 static_cast<int>(CViewStateSettings::GetInstance().GetSettingLevel()));
114 // only re-create the categories, the settings will be created later
115 SetupControls(false);
118 // try to find the category that was previously selected
119 if (!oldCategory
.empty())
121 for (int i
= 0; i
< static_cast<int>(m_categories
.size()); i
++)
123 if (m_categories
[i
]->GetId() == oldCategory
)
139 return CGUIDialogSettingsManagerBase::OnAction(action
);
142 bool CGUIDialogAddonSettings::ShowForAddon(const ADDON::AddonPtr
& addon
,
143 bool saveToDisk
/* = true */)
147 CLog::LogF(LOGERROR
, "No addon given!");
151 if (addon
->Type() == ADDON::AddonType::GAME_CONTROLLER
)
153 CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_DIALOG_GAME_CONTROLLERS
,
158 if (!g_passwordManager
.CheckMenuLock(WINDOW_ADDON_BROWSER
))
161 if (addon
->SupportsInstanceSettings())
162 return ShowForMultipleInstances(addon
, saveToDisk
);
164 return ShowForSingleInstance(addon
, saveToDisk
);
167 bool CGUIDialogAddonSettings::ShowForSingleInstance(
168 const ADDON::AddonPtr
& addon
,
170 ADDON::AddonInstanceId instanceId
/* = ADDON::ADDON_SETTINGS_ID */)
172 if (!addon
->HasSettings(instanceId
))
174 // addon does not support settings, inform user
175 HELPERS::ShowOKDialogText(CVariant
{24000}, CVariant
{24030});
180 CGUIDialogAddonSettings
* dialog
=
181 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogAddonSettings
>(
182 WINDOW_DIALOG_ADDON_SETTINGS
);
185 CLog::LogF(LOGERROR
, "Unable to get WINDOW_DIALOG_ADDON_SETTINGS instance!");
189 dialog
->m_addon
= addon
;
190 dialog
->m_instanceId
= instanceId
;
191 dialog
->m_saveToDisk
= saveToDisk
;
195 if (!dialog
->IsConfirmed())
197 addon
->ReloadSettings(instanceId
);
202 addon
->SaveSettings(instanceId
);
207 bool CGUIDialogAddonSettings::ShowForMultipleInstances(const ADDON::AddonPtr
& addon
,
210 CGUIDialogSelect
* dialog
=
211 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogSelect
>(
212 WINDOW_DIALOG_SELECT
);
215 CLog::LogF(LOGERROR
, "Unable to get WINDOW_DIALOG_SELECT instance!");
219 int lastSelected
= -1;
222 std::vector
<ADDON::AddonInstanceId
> ids
= addon
->GetKnownInstanceIds();
223 std::sort(ids
.begin(), ids
.end(), [](const auto& a
, const auto& b
) { return a
< b
; });
226 dialog
->SetHeading(10012); // Add-on configurations and settings
227 dialog
->SetUseDetails(false);
229 CFileItemList itemsInstances
;
230 ADDON::AddonInstanceId highestId
= 0;
231 for (const auto& id
: ids
)
234 addon
->GetSettingString(ADDON_SETTING_INSTANCE_NAME_VALUE
, name
, id
);
236 name
= g_localizeStrings
.Get(13205); // Unknown
238 bool enabled
= false;
239 addon
->GetSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE
, enabled
, id
);
241 const std::string label
= StringUtils::Format(
242 g_localizeStrings
.Get(10020), name
,
243 g_localizeStrings
.Get(enabled
? 305 : 13106)); // Edit "config name" [enabled state]
245 const CFileItemPtr item
= std::make_shared
<CFileItem
>(label
);
246 item
->SetProperty("id", id
);
247 item
->SetProperty("name", name
);
248 itemsInstances
.Add(item
);
254 CFileItemList itemsGeneral
;
256 const ADDON::AddonInstanceId addInstanceId
= highestId
+ 1;
257 const ADDON::AddonInstanceId removeInstanceId
= highestId
+ 2;
260 std::make_shared
<CFileItem
>(g_localizeStrings
.Get(10014)); // Add add-on configuration
261 item
->SetProperty("id", addInstanceId
);
262 itemsGeneral
.Add(item
);
264 if (ids
.size() > 1) // Forbid removal of last instance
267 std::make_shared
<CFileItem
>(g_localizeStrings
.Get(10015)); // Remove add-on configuration
268 item
->SetProperty("id", removeInstanceId
);
269 itemsGeneral
.Add(item
);
272 if (addon
->HasSettings(ADDON_SETTINGS_ID
))
274 item
= std::make_shared
<CFileItem
>(g_localizeStrings
.Get(10013)); // Edit Add-on settings
275 item
->SetProperty("id", ADDON_SETTINGS_ID
);
276 itemsGeneral
.Add(item
);
279 for (auto& it
: itemsGeneral
)
282 for (auto& it
: itemsInstances
)
285 // Select last selected item, first instance config item or first item
286 if (lastSelected
>= 0)
287 dialog
->SetSelected(lastSelected
);
289 dialog
->SetSelected(itemsInstances
.Size() > 0 ? itemsGeneral
.Size() : 0);
293 if (dialog
->IsButtonPressed() || !dialog
->IsConfirmed())
296 lastSelected
= dialog
->GetSelectedItem();
298 item
= dialog
->GetSelectedFileItem();
299 ADDON::AddonInstanceId instanceId
= item
->GetProperty("id").asInteger();
301 if (instanceId
== addInstanceId
)
303 instanceId
= highestId
+ 1;
305 addon
->GetSettings(instanceId
);
306 addon
->UpdateSettingString(ADDON_SETTING_INSTANCE_NAME_VALUE
, "", instanceId
);
307 addon
->UpdateSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE
, true, instanceId
);
308 addon
->SaveSettings(instanceId
);
310 if (ShowForSingleInstance(addon
, saveToDisk
, instanceId
))
312 CServiceBroker::GetAddonMgr().PublishInstanceAdded(addon
->ID(), instanceId
);
316 // Remove instance settings if not succeeded (e.g. dialog cancelled)
317 addon
->DeleteInstanceSettings(instanceId
);
320 else if (instanceId
== removeInstanceId
)
323 dialog
->SetHeading(10010); // Select add-on configuration to remove
324 dialog
->SetUseDetails(false);
326 for (auto& it
: itemsInstances
)
329 item
.SetLabel((*it
).GetProperty("name").asString());
333 dialog
->SetSelected(0);
336 if (!dialog
->IsButtonPressed() && dialog
->IsConfirmed())
338 item
= dialog
->GetSelectedFileItem();
339 const std::string label
= StringUtils::Format(
340 g_localizeStrings
.Get(10019),
341 item
->GetProperty("name")
342 .asString()); // Do you want to remove the add-on configuration "config name"?
344 if (CGUIDialogYesNo::ShowAndGetInput(10009, // Confirm add-on configuration removal
347 instanceId
= item
->GetProperty("id").asInteger();
348 addon
->DeleteInstanceSettings(instanceId
);
349 CServiceBroker::GetAddonMgr().PublishInstanceRemoved(addon
->ID(), instanceId
);
355 // edit instance settings or edit addon settings selected; open settings dialog
357 bool enabled
= false;
358 addon
->GetSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE
, enabled
, instanceId
);
360 if (ShowForSingleInstance(addon
, saveToDisk
, instanceId
) && instanceId
!= ADDON_SETTINGS_ID
)
362 // Publish new/removed instance configuration and start the use of new instance
363 bool enabledNow
= false;
364 addon
->GetSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE
, enabledNow
, instanceId
);
365 if (enabled
!= enabledNow
)
368 CServiceBroker::GetAddonMgr().PublishInstanceAdded(addon
->ID(), instanceId
);
370 CServiceBroker::GetAddonMgr().PublishInstanceRemoved(addon
->ID(), instanceId
);
375 // refresh selection dialog content...
382 void CGUIDialogAddonSettings::SaveAndClose()
384 if (!g_passwordManager
.CheckMenuLock(WINDOW_ADDON_BROWSER
))
388 CGUIDialogAddonSettings
* dialog
=
389 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogAddonSettings
>(
390 WINDOW_DIALOG_ADDON_SETTINGS
);
391 if (dialog
== nullptr || !dialog
->IsActive())
394 // check if we need to save the settings
395 if (dialog
->m_saveToDisk
&& dialog
->m_addon
!= nullptr)
396 dialog
->m_addon
->SaveSettings(dialog
->m_instanceId
);
402 std::string
CGUIDialogAddonSettings::GetCurrentAddonID() const
404 if (m_addon
== nullptr)
407 return m_addon
->ID();
410 void CGUIDialogAddonSettings::SetupView()
412 if (m_addon
== nullptr || m_addon
->GetSettings(m_instanceId
) == nullptr)
415 auto settings
= m_addon
->GetSettings(m_instanceId
);
416 if (!settings
->IsLoaded())
419 CGUIDialogSettingsManagerBase::SetupView();
421 // set addon id as window property
422 SetProperty("Addon.ID", m_addon
->ID());
425 SetHeading(StringUtils::Format("$LOCALIZE[10004] - {}",
426 m_addon
->Name())); // "Settings - AddonName"
428 // set control labels
429 SET_CONTROL_LABEL(CONTROL_SETTINGS_OKAY_BUTTON
, 186);
430 SET_CONTROL_LABEL(CONTROL_SETTINGS_CANCEL_BUTTON
, 222);
431 SET_CONTROL_LABEL(CONTROL_SETTINGS_CUSTOM_BUTTON
, 409);
432 SET_CONTROL_LABEL(CONTROL_BTN_LEVELS
,
433 10036 + static_cast<int>(CViewStateSettings::GetInstance().GetSettingLevel()));
436 std::string
CGUIDialogAddonSettings::GetLocalizedString(uint32_t labelId
) const
438 std::string label
= g_localizeStrings
.GetAddonString(m_addon
->ID(), labelId
);
442 return CGUIDialogSettingsManagerBase::GetLocalizedString(labelId
);
445 std::string
CGUIDialogAddonSettings::GetSettingsLabel(const std::shared_ptr
<ISetting
>& setting
)
447 if (setting
== nullptr)
450 std::string label
= GetLocalizedString(setting
->GetLabel());
454 // try the addon settings
455 label
= m_addon
->GetSettings(m_instanceId
)->GetSettingLabel(setting
->GetLabel());
459 return CGUIDialogSettingsManagerBase::GetSettingsLabel(setting
);
462 int CGUIDialogAddonSettings::GetSettingLevel() const
464 return static_cast<int>(CViewStateSettings::GetInstance().GetSettingLevel());
467 std::shared_ptr
<CSettingSection
> CGUIDialogAddonSettings::GetSection()
469 const auto settingsManager
= GetSettingsManager();
470 if (settingsManager
== nullptr)
473 const auto sections
= settingsManager
->GetSections();
474 if (!sections
.empty())
475 return sections
.front();
480 CSettingsManager
* CGUIDialogAddonSettings::GetSettingsManager() const
482 if (m_addon
== nullptr || m_addon
->GetSettings(m_instanceId
) == nullptr)
485 return m_addon
->GetSettings(m_instanceId
)->GetSettingsManager();
488 void CGUIDialogAddonSettings::OnSettingAction(const std::shared_ptr
<const CSetting
>& setting
)
490 if (m_addon
== nullptr || m_addon
->GetSettings(m_instanceId
) == nullptr)
493 m_addon
->GetSettings(m_instanceId
)->OnSettingAction(setting
);