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 "GUIControlSettings.h"
12 #include "ServiceBroker.h"
14 #include "addons/AddonManager.h"
15 #include "addons/gui/GUIWindowAddonBrowser.h"
16 #include "addons/settings/SettingUrlEncodedString.h"
17 #include "dialogs/GUIDialogColorPicker.h"
18 #include "dialogs/GUIDialogFileBrowser.h"
19 #include "dialogs/GUIDialogNumeric.h"
20 #include "dialogs/GUIDialogSelect.h"
21 #include "dialogs/GUIDialogSlider.h"
22 #include "guilib/GUIColorButtonControl.h"
23 #include "guilib/GUIComponent.h"
24 #include "guilib/GUIEditControl.h"
25 #include "guilib/GUIImage.h"
26 #include "guilib/GUIKeyboardFactory.h"
27 #include "guilib/GUILabelControl.h"
28 #include "guilib/GUIRadioButtonControl.h"
29 #include "guilib/GUISettingsSliderControl.h"
30 #include "guilib/GUISpinControlEx.h"
31 #include "guilib/GUIWindowManager.h"
32 #include "guilib/LocalizeStrings.h"
33 #include "settings/MediaSourceSettings.h"
34 #include "settings/SettingAddon.h"
35 #include "settings/SettingControl.h"
36 #include "settings/SettingDateTime.h"
37 #include "settings/SettingPath.h"
38 #include "settings/SettingUtils.h"
39 #include "settings/lib/Setting.h"
40 #include "settings/lib/SettingDefinitions.h"
41 #include "storage/MediaManager.h"
42 #include "utils/FileExtensionProvider.h"
43 #include "utils/StringUtils.h"
44 #include "utils/Variant.h"
45 #include "utils/log.h"
50 using namespace ADDON
;
52 static std::string
Localize(std::uint32_t code
,
53 ILocalizer
* localizer
,
54 const std::string
& addonId
= "")
56 if (localizer
== nullptr)
61 std::string label
= g_localizeStrings
.GetAddonString(addonId
, code
);
66 return localizer
->Localize(code
);
69 template<typename TValueType
>
70 static CFileItemPtr
GetFileItem(const std::string
& label
,
71 const std::string
& label2
,
72 const TValueType
& value
,
73 const std::vector
<std::pair
<std::string
, CVariant
>>& properties
,
74 const std::set
<TValueType
>& selectedValues
)
76 CFileItemPtr
item(new CFileItem(label
));
77 item
->SetProperty("value", value
);
78 item
->SetLabel2(label2
);
80 for (const auto& prop
: properties
)
81 item
->SetProperty(prop
.first
, prop
.second
);
83 if (selectedValues
.find(value
) != selectedValues
.end())
89 template<class SettingOption
>
90 static bool CompareSettingOptionAseconding(const SettingOption
& lhs
, const SettingOption
& rhs
)
92 return StringUtils::CompareNoCase(lhs
.label
, rhs
.label
) < 0;
95 template<class SettingOption
>
96 static bool CompareSettingOptionDeseconding(const SettingOption
& lhs
, const SettingOption
& rhs
)
98 return StringUtils::CompareNoCase(lhs
.label
, rhs
.label
) > 0;
101 static bool GetIntegerOptions(const SettingConstPtr
& setting
,
102 IntegerSettingOptions
& options
,
103 std::set
<int>& selectedOptions
,
104 ILocalizer
* localizer
,
107 std::shared_ptr
<const CSettingInt
> pSettingInt
= NULL
;
108 if (setting
->GetType() == SettingType::Integer
)
109 pSettingInt
= std::static_pointer_cast
<const CSettingInt
>(setting
);
110 else if (setting
->GetType() == SettingType::List
)
112 std::shared_ptr
<const CSettingList
> settingList
=
113 std::static_pointer_cast
<const CSettingList
>(setting
);
114 if (settingList
->GetElementType() != SettingType::Integer
)
117 pSettingInt
= std::static_pointer_cast
<const CSettingInt
>(settingList
->GetDefinition());
120 switch (pSettingInt
->GetOptionsType())
122 case SettingOptionsType::StaticTranslatable
:
124 const TranslatableIntegerSettingOptions
& settingOptions
=
125 pSettingInt
->GetTranslatableOptions();
126 for (const auto& option
: settingOptions
)
128 IntegerSettingOption(Localize(option
.label
, localizer
, option
.addonId
), option
.value
));
132 case SettingOptionsType::Static
:
134 const IntegerSettingOptions
& settingOptions
= pSettingInt
->GetOptions();
135 options
.insert(options
.end(), settingOptions
.begin(), settingOptions
.end());
139 case SettingOptionsType::Dynamic
:
141 IntegerSettingOptions settingOptions
;
143 settingOptions
= std::const_pointer_cast
<CSettingInt
>(pSettingInt
)->UpdateDynamicOptions();
145 settingOptions
= pSettingInt
->GetDynamicOptions();
146 options
.insert(options
.end(), settingOptions
.begin(), settingOptions
.end());
150 case SettingOptionsType::Unknown
:
153 std::shared_ptr
<const CSettingControlFormattedRange
> control
=
154 std::static_pointer_cast
<const CSettingControlFormattedRange
>(pSettingInt
->GetControl());
155 for (int i
= pSettingInt
->GetMinimum(); i
<= pSettingInt
->GetMaximum();
156 i
+= pSettingInt
->GetStep())
158 std::string strLabel
;
159 if (i
== pSettingInt
->GetMinimum() && control
->GetMinimumLabel() > -1)
160 strLabel
= Localize(control
->GetMinimumLabel(), localizer
);
161 else if (control
->GetFormatLabel() > -1)
162 strLabel
= StringUtils::Format(Localize(control
->GetFormatLabel(), localizer
), i
);
164 strLabel
= StringUtils::Format(control
->GetFormatString(), i
);
166 options
.push_back(IntegerSettingOption(strLabel
, i
));
173 switch (pSettingInt
->GetOptionsSort())
175 case SettingOptionsSort::Ascending
:
176 std::sort(options
.begin(), options
.end(),
177 CompareSettingOptionAseconding
<IntegerSettingOption
>);
180 case SettingOptionsSort::Descending
:
181 std::sort(options
.begin(), options
.end(),
182 CompareSettingOptionDeseconding
<IntegerSettingOption
>);
185 case SettingOptionsSort::NoSorting
:
190 // this must be done after potentially calling CSettingInt::UpdateDynamicOptions() because it can
191 // change the value of the setting
192 if (setting
->GetType() == SettingType::Integer
)
193 selectedOptions
.insert(pSettingInt
->GetValue());
194 else if (setting
->GetType() == SettingType::List
)
196 std::vector
<CVariant
> list
=
197 CSettingUtils::GetList(std::static_pointer_cast
<const CSettingList
>(setting
));
198 for (const auto& itValue
: list
)
199 selectedOptions
.insert((int)itValue
.asInteger());
207 static bool GetStringOptions(const SettingConstPtr
& setting
,
208 StringSettingOptions
& options
,
209 std::set
<std::string
>& selectedOptions
,
210 ILocalizer
* localizer
,
213 std::shared_ptr
<const CSettingString
> pSettingString
= NULL
;
214 if (setting
->GetType() == SettingType::String
)
215 pSettingString
= std::static_pointer_cast
<const CSettingString
>(setting
);
216 else if (setting
->GetType() == SettingType::List
)
218 std::shared_ptr
<const CSettingList
> settingList
=
219 std::static_pointer_cast
<const CSettingList
>(setting
);
220 if (settingList
->GetElementType() != SettingType::String
)
223 pSettingString
= std::static_pointer_cast
<const CSettingString
>(settingList
->GetDefinition());
226 switch (pSettingString
->GetOptionsType())
228 case SettingOptionsType::StaticTranslatable
:
230 const TranslatableStringSettingOptions
& settingOptions
=
231 pSettingString
->GetTranslatableOptions();
232 for (const auto& option
: settingOptions
)
233 options
.push_back(StringSettingOption(Localize(option
.first
, localizer
), option
.second
));
237 case SettingOptionsType::Static
:
239 const StringSettingOptions
& settingOptions
= pSettingString
->GetOptions();
240 options
.insert(options
.end(), settingOptions
.begin(), settingOptions
.end());
244 case SettingOptionsType::Dynamic
:
246 StringSettingOptions settingOptions
;
249 std::const_pointer_cast
<CSettingString
>(pSettingString
)->UpdateDynamicOptions();
251 settingOptions
= pSettingString
->GetDynamicOptions();
252 options
.insert(options
.end(), settingOptions
.begin(), settingOptions
.end());
256 case SettingOptionsType::Unknown
:
261 switch (pSettingString
->GetOptionsSort())
263 case SettingOptionsSort::Ascending
:
264 std::sort(options
.begin(), options
.end(),
265 CompareSettingOptionAseconding
<StringSettingOption
>);
268 case SettingOptionsSort::Descending
:
269 std::sort(options
.begin(), options
.end(),
270 CompareSettingOptionDeseconding
<StringSettingOption
>);
273 case SettingOptionsSort::NoSorting
:
278 // this must be done after potentially calling CSettingString::UpdateDynamicOptions() because it
279 // can change the value of the setting
280 if (setting
->GetType() == SettingType::String
)
281 selectedOptions
.insert(pSettingString
->GetValue());
282 else if (setting
->GetType() == SettingType::List
)
284 std::vector
<CVariant
> list
=
285 CSettingUtils::GetList(std::static_pointer_cast
<const CSettingList
>(setting
));
286 for (const auto& itValue
: list
)
287 selectedOptions
.insert(itValue
.asString());
295 CGUIControlBaseSetting::CGUIControlBaseSetting(int id
,
296 std::shared_ptr
<CSetting
> pSetting
,
297 ILocalizer
* localizer
)
299 m_pSetting(std::move(pSetting
)),
300 m_localizer(localizer
),
306 bool CGUIControlBaseSetting::IsEnabled() const
308 return m_pSetting
!= NULL
&& m_pSetting
->IsEnabled();
311 void CGUIControlBaseSetting::UpdateFromControl()
316 void CGUIControlBaseSetting::UpdateFromSetting(bool updateDisplayOnly
/* = false */)
318 Update(false, updateDisplayOnly
);
321 std::string
CGUIControlBaseSetting::Localize(std::uint32_t code
) const
323 return ::Localize(code
, m_localizer
);
326 void CGUIControlBaseSetting::Update(bool fromControl
, bool updateDisplayOnly
)
328 if (fromControl
|| updateDisplayOnly
)
331 CGUIControl
* control
= GetControl();
335 control
->SetEnabled(IsEnabled());
337 control
->SetVisible(m_pSetting
->IsVisible());
341 CGUIControlRadioButtonSetting::CGUIControlRadioButtonSetting(CGUIRadioButtonControl
* pRadioButton
,
343 std::shared_ptr
<CSetting
> pSetting
,
344 ILocalizer
* localizer
)
345 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
347 m_pRadioButton
= pRadioButton
;
348 if (m_pRadioButton
== NULL
)
351 m_pRadioButton
->SetID(id
);
354 CGUIControlRadioButtonSetting::~CGUIControlRadioButtonSetting() = default;
356 bool CGUIControlRadioButtonSetting::OnClick()
358 SetValid(std::static_pointer_cast
<CSettingBool
>(m_pSetting
)
359 ->SetValue(!std::static_pointer_cast
<CSettingBool
>(m_pSetting
)->GetValue()));
363 void CGUIControlRadioButtonSetting::Update(bool fromControl
, bool updateDisplayOnly
)
365 if (fromControl
|| m_pRadioButton
== NULL
)
368 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
370 m_pRadioButton
->SetSelected(std::static_pointer_cast
<CSettingBool
>(m_pSetting
)->GetValue());
373 CGUIControlColorButtonSetting::CGUIControlColorButtonSetting(
374 CGUIColorButtonControl
* pColorControl
,
376 const std::shared_ptr
<CSetting
>& pSetting
,
377 ILocalizer
* localizer
)
378 : CGUIControlBaseSetting(id
, pSetting
, localizer
)
380 m_pColorButton
= pColorControl
;
384 m_pColorButton
->SetID(id
);
387 CGUIControlColorButtonSetting::~CGUIControlColorButtonSetting() = default;
389 bool CGUIControlColorButtonSetting::OnClick()
394 std::shared_ptr
<CSettingString
> settingHexColor
=
395 std::static_pointer_cast
<CSettingString
>(m_pSetting
);
397 CGUIDialogColorPicker
* dialog
=
398 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogColorPicker
>(
399 WINDOW_DIALOG_COLOR_PICKER
);
404 dialog
->SetHeading(CVariant
{Localize(m_pSetting
->GetLabel())});
405 dialog
->LoadColors();
406 std::string hexColor
;
408 hexColor
= settingHexColor
.get()->GetValue();
409 dialog
->SetSelectedColor(hexColor
);
412 if (!dialog
->IsConfirmed())
416 std::static_pointer_cast
<CSettingString
>(m_pSetting
)->SetValue(dialog
->GetSelectedColor()));
420 void CGUIControlColorButtonSetting::Update(bool fromControl
, bool updateDisplayOnly
)
422 if (fromControl
|| !m_pColorButton
)
425 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
426 // Set the color to apply to the preview color box
427 m_pColorButton
->SetImageBoxColor(
428 std::static_pointer_cast
<CSettingString
>(m_pSetting
)->GetValue());
431 CGUIControlSpinExSetting::CGUIControlSpinExSetting(CGUISpinControlEx
* pSpin
,
433 std::shared_ptr
<CSetting
> pSetting
,
434 ILocalizer
* localizer
)
435 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
443 const std::string
& controlFormat
= m_pSetting
->GetControl()->GetFormat();
444 if (controlFormat
== "number")
446 std::shared_ptr
<CSettingNumber
> pSettingNumber
=
447 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
448 m_pSpin
->SetType(SPIN_CONTROL_TYPE_FLOAT
);
449 m_pSpin
->SetFloatRange(static_cast<float>(pSettingNumber
->GetMinimum()),
450 static_cast<float>(pSettingNumber
->GetMaximum()));
451 m_pSpin
->SetFloatInterval(static_cast<float>(pSettingNumber
->GetStep()));
453 else if (controlFormat
== "integer")
454 m_pSpin
->SetType(SPIN_CONTROL_TYPE_TEXT
);
455 else if (controlFormat
== "string")
457 m_pSpin
->SetType(SPIN_CONTROL_TYPE_TEXT
);
459 if (m_pSetting
->GetType() == SettingType::Integer
)
460 FillIntegerSettingControl(false);
461 else if (m_pSetting
->GetType() == SettingType::Number
)
463 std::shared_ptr
<CSettingNumber
> pSettingNumber
=
464 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
465 std::shared_ptr
<const CSettingControlFormattedRange
> control
=
466 std::static_pointer_cast
<const CSettingControlFormattedRange
>(m_pSetting
->GetControl());
468 for (double value
= pSettingNumber
->GetMinimum(); value
<= pSettingNumber
->GetMaximum();
469 value
+= pSettingNumber
->GetStep(), index
++)
471 std::string strLabel
;
472 if (value
== pSettingNumber
->GetMinimum() && control
->GetMinimumLabel() > -1)
473 strLabel
= Localize(control
->GetMinimumLabel());
474 else if (control
->GetFormatLabel() > -1)
475 strLabel
= StringUtils::Format(Localize(control
->GetFormatLabel()), value
);
477 strLabel
= StringUtils::Format(control
->GetFormatString(), value
);
479 m_pSpin
->AddLabel(strLabel
, index
);
485 CGUIControlSpinExSetting::~CGUIControlSpinExSetting() = default;
487 bool CGUIControlSpinExSetting::OnClick()
492 switch (m_pSetting
->GetType())
494 case SettingType::Integer
:
495 SetValid(std::static_pointer_cast
<CSettingInt
>(m_pSetting
)->SetValue(m_pSpin
->GetValue()));
498 case SettingType::Number
:
500 auto pSettingNumber
= std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
501 const auto& controlFormat
= m_pSetting
->GetControl()->GetFormat();
502 if (controlFormat
== "number")
503 SetValid(pSettingNumber
->SetValue(static_cast<double>(m_pSpin
->GetFloatValue())));
505 SetValid(pSettingNumber
->SetValue(pSettingNumber
->GetMinimum() +
506 pSettingNumber
->GetStep() * m_pSpin
->GetValue()));
511 case SettingType::String
:
512 SetValid(std::static_pointer_cast
<CSettingString
>(m_pSetting
)
513 ->SetValue(m_pSpin
->GetStringValue()));
523 void CGUIControlSpinExSetting::Update(bool fromControl
, bool updateDisplayOnly
)
525 if (fromControl
|| m_pSpin
== NULL
)
528 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
530 FillControl(!updateDisplayOnly
);
532 if (!updateDisplayOnly
)
534 // disable the spinner if it has less than two items
535 if (!m_pSpin
->IsDisabled() && (m_pSpin
->GetMaximum() - m_pSpin
->GetMinimum()) == 0)
536 m_pSpin
->SetEnabled(false);
540 void CGUIControlSpinExSetting::FillControl(bool updateValues
)
548 const std::string
& controlFormat
= m_pSetting
->GetControl()->GetFormat();
549 if (controlFormat
== "number")
551 std::shared_ptr
<CSettingNumber
> pSettingNumber
=
552 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
553 m_pSpin
->SetFloatValue((float)pSettingNumber
->GetValue());
555 else if (controlFormat
== "integer")
556 FillIntegerSettingControl(updateValues
);
557 else if (controlFormat
== "string")
559 if (m_pSetting
->GetType() == SettingType::Integer
)
560 FillIntegerSettingControl(updateValues
);
561 else if (m_pSetting
->GetType() == SettingType::Number
)
562 FillFloatSettingControl();
563 else if (m_pSetting
->GetType() == SettingType::String
)
564 FillStringSettingControl(updateValues
);
568 void CGUIControlSpinExSetting::FillIntegerSettingControl(bool updateValues
)
570 IntegerSettingOptions options
;
571 std::set
<int> selectedValues
;
572 // get the integer options
573 if (!GetIntegerOptions(m_pSetting
, options
, selectedValues
, m_localizer
, updateValues
) ||
574 selectedValues
.size() != 1)
579 // add them to the spinner
580 for (const auto& option
: options
)
581 m_pSpin
->AddLabel(option
.label
, option
.value
);
584 // and set the current value
585 m_pSpin
->SetValue(*selectedValues
.begin());
588 void CGUIControlSpinExSetting::FillFloatSettingControl()
590 std::shared_ptr
<CSettingNumber
> pSettingNumber
=
591 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
592 std::shared_ptr
<const CSettingControlFormattedRange
> control
=
593 std::static_pointer_cast
<const CSettingControlFormattedRange
>(m_pSetting
->GetControl());
595 int currentIndex
= 0;
596 for (double value
= pSettingNumber
->GetMinimum(); value
<= pSettingNumber
->GetMaximum();
597 value
+= pSettingNumber
->GetStep(), index
++)
599 if (value
== pSettingNumber
->GetValue())
601 currentIndex
= index
;
606 m_pSpin
->SetValue(currentIndex
);
609 void CGUIControlSpinExSetting::FillStringSettingControl(bool updateValues
)
611 StringSettingOptions options
;
612 std::set
<std::string
> selectedValues
;
613 // get the string options
614 if (!GetStringOptions(m_pSetting
, options
, selectedValues
, m_localizer
, updateValues
) ||
615 selectedValues
.size() != 1)
620 // add them to the spinner
621 for (const auto& option
: options
)
622 m_pSpin
->AddLabel(option
.label
, option
.value
);
625 // and set the current value
626 m_pSpin
->SetStringValue(*selectedValues
.begin());
629 CGUIControlListSetting::CGUIControlListSetting(CGUIButtonControl
* pButton
,
631 std::shared_ptr
<CSetting
> pSetting
,
632 ILocalizer
* localizer
)
633 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
636 if (m_pButton
== NULL
)
639 m_pButton
->SetID(id
);
642 CGUIControlListSetting::~CGUIControlListSetting() = default;
644 bool CGUIControlListSetting::OnClick()
646 if (m_pButton
== NULL
)
649 CGUIDialogSelect
* dialog
=
650 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogSelect
>(
651 WINDOW_DIALOG_SELECT
);
655 CFileItemList options
;
656 std::shared_ptr
<const CSettingControlList
> control
=
657 std::static_pointer_cast
<const CSettingControlList
>(m_pSetting
->GetControl());
658 bool optionsValid
= GetItems(m_pSetting
, options
, false);
660 bool bValueAdded
= false;
661 bool bAllowNewOption
= false;
662 if (m_pSetting
->GetType() == SettingType::List
)
664 std::shared_ptr
<const CSettingList
> settingList
=
665 std::static_pointer_cast
<const CSettingList
>(m_pSetting
);
666 if (settingList
->GetElementType() == SettingType::String
)
668 bAllowNewOption
= std::static_pointer_cast
<const CSettingString
>(settingList
->GetDefinition())
672 if (!bAllowNewOption
)
674 // Do not show dialog if
675 // there are no items to be chosen
676 if (!optionsValid
|| options
.Size() <= 0)
680 dialog
->SetHeading(CVariant
{Localize(m_pSetting
->GetLabel())});
681 dialog
->SetItems(options
);
682 dialog
->SetMultiSelection(control
->CanMultiSelect());
683 dialog
->SetUseDetails(control
->UseDetails());
686 if (!dialog
->IsConfirmed())
691 // Possible to add items, as well as select from any options given
692 // Add any current values that are not options as items in list
693 std::vector
<CVariant
> list
=
694 CSettingUtils::GetList(std::static_pointer_cast
<const CSettingList
>(m_pSetting
));
695 for (const auto& value
: list
)
697 bool found
= std::any_of(options
.begin(), options
.end(), [&](const auto& p
) {
698 return p
->GetProperty("value").asString() == value
.asString();
702 CFileItemPtr
item(new CFileItem(value
.asString()));
703 item
->SetProperty("value", value
.asString());
712 std::string strAddButton
= Localize(control
->GetAddButtonLabel());
713 if (strAddButton
.empty())
714 strAddButton
= Localize(15019); // "ADD"
715 dialog
->Reset(); // Clears AddButtonPressed
716 dialog
->SetHeading(CVariant
{ Localize(m_pSetting
->GetLabel()) });
717 dialog
->SetItems(options
);
718 dialog
->SetMultiSelection(control
->CanMultiSelect());
719 dialog
->EnableButton2(bAllowNewOption
, strAddButton
);
723 if (!dialog
->IsConfirmed())
726 if (dialog
->IsButton2Pressed())
728 // Get new list value
729 std::string strLabel
;
730 bool bValidType
= false;
731 while (!bValidType
&& CGUIKeyboardFactory::ShowAndGetInput(
732 strLabel
, CVariant
{ Localize(control
->GetAddButtonLabel()) }, false))
734 // Validate new value is unique and truncate at any comma
735 StringUtils::Trim(strLabel
);
736 strLabel
= strLabel
.substr(0, strLabel
.find(','));
737 if (!strLabel
.empty())
739 bValidType
= !std::any_of(options
.begin(), options
.end(), [&](const auto& p
) {
740 return p
->GetProperty("value").asString() == strLabel
;
744 { // Add new value to the list of options
745 CFileItemPtr
pItem(new CFileItem(strLabel
));
747 pItem
->SetProperty("value", strLabel
);
753 bRepeat
= dialog
->IsButton2Pressed();
757 std::vector
<CVariant
> values
;
758 for (int i
: dialog
->GetSelectedItems())
760 const CFileItemPtr item
= options
.Get(i
);
761 if (item
== NULL
|| !item
->HasProperty("value"))
764 values
.push_back(item
->GetProperty("value"));
768 switch (m_pSetting
->GetType())
770 case SettingType::Integer
:
771 if (values
.size() > 1)
773 ret
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
)
774 ->SetValue((int)values
.at(0).asInteger());
777 case SettingType::String
:
778 if (values
.size() > 1)
780 ret
= std::static_pointer_cast
<CSettingString
>(m_pSetting
)->SetValue(values
.at(0).asString());
783 case SettingType::List
:
784 ret
= CSettingUtils::SetList(std::static_pointer_cast
<CSettingList
>(m_pSetting
), values
);
792 UpdateFromSetting(!bValueAdded
);
799 void CGUIControlListSetting::Update(bool fromControl
, bool updateDisplayOnly
)
801 if (fromControl
|| m_pButton
== NULL
)
804 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
806 CFileItemList options
;
807 std::shared_ptr
<const CSettingControlList
> control
=
808 std::static_pointer_cast
<const CSettingControlList
>(m_pSetting
->GetControl());
809 bool optionsValid
= GetItems(m_pSetting
, options
, !updateDisplayOnly
);
811 bool bAllowNewOption
= false;
812 if (m_pSetting
->GetType() == SettingType::List
)
814 std::shared_ptr
<const CSettingList
> settingList
=
815 std::static_pointer_cast
<const CSettingList
>(m_pSetting
);
816 if (settingList
->GetElementType() == SettingType::String
)
818 bAllowNewOption
= std::static_pointer_cast
<const CSettingString
>(settingList
->GetDefinition())
824 if (optionsValid
&& !control
->HideValue())
826 SettingControlListValueFormatter formatter
= control
->GetFormatter();
828 label2
= formatter(m_pSetting
);
830 if (label2
.empty() && bAllowNewOption
)
832 const std::shared_ptr
<const CSettingList
> settingList
=
833 std::static_pointer_cast
<const CSettingList
>(m_pSetting
);
834 label2
= settingList
->ToString();
839 std::vector
<std::string
> labels
;
840 for (int index
= 0; index
< options
.Size(); index
++)
842 const CFileItemPtr pItem
= options
.Get(index
);
843 if (pItem
->IsSelected())
844 labels
.push_back(pItem
->GetLabel());
847 label2
= StringUtils::Join(labels
, ", ");
851 m_pButton
->SetLabel2(label2
);
853 if (!updateDisplayOnly
)
855 // Disable the control if no items can be added and
856 // there are no items to be chosen
857 if (!m_pButton
->IsDisabled() && !bAllowNewOption
&& (options
.Size() <= 0))
858 m_pButton
->SetEnabled(false);
862 bool CGUIControlListSetting::GetItems(const SettingConstPtr
& setting
,
863 CFileItemList
& items
,
864 bool updateItems
) const
866 std::shared_ptr
<const CSettingControlList
> control
=
867 std::static_pointer_cast
<const CSettingControlList
>(setting
->GetControl());
868 const std::string
& controlFormat
= control
->GetFormat();
870 if (controlFormat
== "integer")
871 return GetIntegerItems(setting
, items
, updateItems
);
872 else if (controlFormat
== "string")
874 if (setting
->GetType() == SettingType::Integer
||
875 (setting
->GetType() == SettingType::List
&&
876 std::static_pointer_cast
<const CSettingList
>(setting
)->GetElementType() ==
877 SettingType::Integer
))
878 return GetIntegerItems(setting
, items
, updateItems
);
879 else if (setting
->GetType() == SettingType::String
||
880 (setting
->GetType() == SettingType::List
&&
881 std::static_pointer_cast
<const CSettingList
>(setting
)->GetElementType() ==
882 SettingType::String
))
883 return GetStringItems(setting
, items
, updateItems
);
891 bool CGUIControlListSetting::GetIntegerItems(const SettingConstPtr
& setting
,
892 CFileItemList
& items
,
893 bool updateItems
) const
895 IntegerSettingOptions options
;
896 std::set
<int> selectedValues
;
897 // get the integer options
898 if (!GetIntegerOptions(setting
, options
, selectedValues
, m_localizer
, updateItems
))
901 // turn them into CFileItems and add them to the item list
902 for (const auto& option
: options
)
904 GetFileItem(option
.label
, option
.label2
, option
.value
, option
.properties
, selectedValues
));
909 bool CGUIControlListSetting::GetStringItems(const SettingConstPtr
& setting
,
910 CFileItemList
& items
,
911 bool updateItems
) const
913 StringSettingOptions options
;
914 std::set
<std::string
> selectedValues
;
915 // get the string options
916 if (!GetStringOptions(setting
, options
, selectedValues
, m_localizer
, updateItems
))
919 // turn them into CFileItems and add them to the item list
920 for (const auto& option
: options
)
922 GetFileItem(option
.label
, option
.label2
, option
.value
, option
.properties
, selectedValues
));
927 CGUIControlButtonSetting::CGUIControlButtonSetting(CGUIButtonControl
* pButton
,
929 std::shared_ptr
<CSetting
> pSetting
,
930 ILocalizer
* localizer
)
931 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
934 if (m_pButton
== NULL
)
937 m_pButton
->SetID(id
);
940 CGUIControlButtonSetting::~CGUIControlButtonSetting() = default;
942 bool CGUIControlButtonSetting::OnClick()
944 if (m_pButton
== NULL
)
947 std::shared_ptr
<const ISettingControl
> control
= m_pSetting
->GetControl();
948 const std::string
& controlType
= control
->GetType();
949 const std::string
& controlFormat
= control
->GetFormat();
950 if (controlType
== "button")
952 std::shared_ptr
<const CSettingControlButton
> buttonControl
=
953 std::static_pointer_cast
<const CSettingControlButton
>(control
);
954 if (controlFormat
== "addon")
956 // prompt for the addon
957 std::shared_ptr
<CSettingAddon
> setting
;
958 std::vector
<std::string
> addonIDs
;
959 if (m_pSetting
->GetType() == SettingType::List
)
961 std::shared_ptr
<CSettingList
> settingList
=
962 std::static_pointer_cast
<CSettingList
>(m_pSetting
);
963 setting
= std::static_pointer_cast
<CSettingAddon
>(settingList
->GetDefinition());
964 for (const SettingPtr
& addon
: settingList
->GetValue())
965 addonIDs
.push_back(std::static_pointer_cast
<CSettingAddon
>(addon
)->GetValue());
969 setting
= std::static_pointer_cast
<CSettingAddon
>(m_pSetting
);
970 addonIDs
.push_back(setting
->GetValue());
973 if (CGUIWindowAddonBrowser::SelectAddonID(
974 setting
->GetAddonType(), addonIDs
, setting
->AllowEmpty(),
975 buttonControl
->ShowAddonDetails(), m_pSetting
->GetType() == SettingType::List
,
976 buttonControl
->ShowInstalledAddons(), buttonControl
->ShowInstallableAddons(),
977 buttonControl
->ShowMoreAddons()) != 1)
980 if (m_pSetting
->GetType() == SettingType::List
)
981 std::static_pointer_cast
<CSettingList
>(m_pSetting
)->FromString(addonIDs
);
983 SetValid(setting
->SetValue(addonIDs
[0]));
985 else if (controlFormat
== "path" || controlFormat
== "file" || controlFormat
== "image")
986 SetValid(GetPath(std::static_pointer_cast
<CSettingPath
>(m_pSetting
), m_localizer
));
987 else if (controlFormat
== "date")
989 std::shared_ptr
<CSettingDate
> settingDate
=
990 std::static_pointer_cast
<CSettingDate
>(m_pSetting
);
992 KODI::TIME::SystemTime systemdate
;
993 settingDate
->GetDate().GetAsSystemTime(systemdate
);
994 if (CGUIDialogNumeric::ShowAndGetDate(systemdate
, Localize(buttonControl
->GetHeading())))
995 SetValid(settingDate
->SetDate(CDateTime(systemdate
)));
997 else if (controlFormat
== "time")
999 std::shared_ptr
<CSettingTime
> settingTime
=
1000 std::static_pointer_cast
<CSettingTime
>(m_pSetting
);
1002 KODI::TIME::SystemTime systemtime
;
1003 settingTime
->GetTime().GetAsSystemTime(systemtime
);
1005 if (CGUIDialogNumeric::ShowAndGetTime(systemtime
, Localize(buttonControl
->GetHeading())))
1006 SetValid(settingTime
->SetTime(CDateTime(systemtime
)));
1008 else if (controlFormat
== "action")
1010 // simply call the OnSettingAction callback and whoever knows what to
1011 // do can do so (based on the setting's identification)
1012 m_pSetting
->OnSettingAction(m_pSetting
);
1016 else if (controlType
== "slider")
1018 float value
, min
, step
, max
;
1019 if (m_pSetting
->GetType() == SettingType::Integer
)
1021 std::shared_ptr
<CSettingInt
> settingInt
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1022 value
= (float)settingInt
->GetValue();
1023 min
= (float)settingInt
->GetMinimum();
1024 step
= (float)settingInt
->GetStep();
1025 max
= (float)settingInt
->GetMaximum();
1027 else if (m_pSetting
->GetType() == SettingType::Number
)
1029 std::shared_ptr
<CSettingNumber
> settingNumber
=
1030 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1031 value
= (float)settingNumber
->GetValue();
1032 min
= (float)settingNumber
->GetMinimum();
1033 step
= (float)settingNumber
->GetStep();
1034 max
= (float)settingNumber
->GetMaximum();
1039 std::shared_ptr
<const CSettingControlSlider
> sliderControl
=
1040 std::static_pointer_cast
<const CSettingControlSlider
>(control
);
1041 CGUIDialogSlider::ShowAndGetInput(Localize(sliderControl
->GetHeading()), value
, min
, step
, max
,
1046 // update the displayed value
1047 UpdateFromSetting(true);
1052 void CGUIControlButtonSetting::Update(bool fromControl
, bool updateDisplayOnly
)
1054 if (fromControl
|| m_pButton
== NULL
)
1057 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
1059 std::string strText
;
1060 std::shared_ptr
<const ISettingControl
> control
= m_pSetting
->GetControl();
1061 const std::string
& controlType
= control
->GetType();
1062 const std::string
& controlFormat
= control
->GetFormat();
1064 if (controlType
== "button")
1066 if (!std::static_pointer_cast
<const CSettingControlButton
>(control
)->HideValue())
1068 auto setting
= m_pSetting
;
1069 if (m_pSetting
->GetType() == SettingType::List
)
1070 setting
= std::static_pointer_cast
<CSettingList
>(m_pSetting
)->GetDefinition();
1072 switch (setting
->GetType())
1074 case SettingType::String
:
1076 if (controlFormat
== "addon")
1078 std::vector
<std::string
> addonIDs
;
1079 if (m_pSetting
->GetType() == SettingType::List
)
1081 for (const auto& addonSetting
:
1082 std::static_pointer_cast
<CSettingList
>(m_pSetting
)->GetValue())
1084 std::static_pointer_cast
<CSettingAddon
>(addonSetting
)->GetValue());
1087 addonIDs
.push_back(std::static_pointer_cast
<CSettingString
>(setting
)->GetValue());
1089 std::vector
<std::string
> addonNames
;
1090 for (const auto& addonID
: addonIDs
)
1092 ADDON::AddonPtr addon
;
1093 if (CServiceBroker::GetAddonMgr().GetAddon(addonID
, addon
,
1094 ADDON::OnlyEnabled::CHOICE_YES
))
1095 addonNames
.push_back(addon
->Name());
1098 if (addonNames
.empty())
1099 strText
= g_localizeStrings
.Get(231); // None
1101 strText
= StringUtils::Join(addonNames
, ", ");
1105 std::string strValue
= std::static_pointer_cast
<CSettingString
>(setting
)->GetValue();
1106 if (controlFormat
== "path" || controlFormat
== "file" || controlFormat
== "image")
1108 std::string shortPath
;
1109 if (CUtil::MakeShortenPath(strValue
, shortPath
, 30))
1110 strText
= shortPath
;
1112 else if (controlFormat
== "infolabel")
1115 if (strText
.empty())
1116 strText
= g_localizeStrings
.Get(231); // None
1125 case SettingType::Action
:
1128 // Note: This can be removed once all settings use a proper control & format combination.
1129 // CSettingAction is strictly speaking not designed to have a label2, it does not even have a value.
1130 strText
= m_pButton
->GetLabel2();
1140 else if (controlType
== "slider")
1142 switch (m_pSetting
->GetType())
1144 case SettingType::Integer
:
1146 std::shared_ptr
<const CSettingInt
> settingInt
=
1147 std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1148 strText
= CGUIControlSliderSetting::GetText(m_pSetting
, settingInt
->GetValue(),
1149 settingInt
->GetMinimum(), settingInt
->GetStep(),
1150 settingInt
->GetMaximum(), m_localizer
);
1154 case SettingType::Number
:
1156 std::shared_ptr
<const CSettingNumber
> settingNumber
=
1157 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1158 strText
= CGUIControlSliderSetting::GetText(
1159 m_pSetting
, settingNumber
->GetValue(), settingNumber
->GetMinimum(),
1160 settingNumber
->GetStep(), settingNumber
->GetMaximum(), m_localizer
);
1169 m_pButton
->SetLabel2(strText
);
1172 bool CGUIControlButtonSetting::GetPath(const std::shared_ptr
<CSettingPath
>& pathSetting
,
1173 ILocalizer
* localizer
)
1175 if (pathSetting
== NULL
)
1178 std::string path
= pathSetting
->GetValue();
1181 bool localSharesOnly
= false;
1182 const std::vector
<std::string
>& sources
= pathSetting
->GetSources();
1183 for (const auto& source
: sources
)
1185 if (StringUtils::EqualsNoCase(source
, "local"))
1186 localSharesOnly
= true;
1189 VECSOURCES
* sources
= CMediaSourceSettings::GetInstance().GetSources(source
);
1190 if (sources
!= NULL
)
1191 shares
.insert(shares
.end(), sources
->begin(), sources
->end());
1195 CServiceBroker::GetMediaManager().GetLocalDrives(shares
);
1196 if (!localSharesOnly
)
1197 CServiceBroker::GetMediaManager().GetNetworkLocations(shares
);
1199 bool result
= false;
1200 std::shared_ptr
<const CSettingControlButton
> control
=
1201 std::static_pointer_cast
<const CSettingControlButton
>(pathSetting
->GetControl());
1202 const auto heading
= ::Localize(control
->GetHeading(), localizer
);
1203 if (control
->GetFormat() == "file")
1204 result
= CGUIDialogFileBrowser::ShowAndGetFile(
1205 shares
, pathSetting
->GetMasking(CServiceBroker::GetFileExtensionProvider()), heading
, path
,
1206 control
->UseImageThumbs(), control
->UseFileDirectories());
1207 else if (control
->GetFormat() == "image")
1209 /* Check setting contains own masking, to filter required image type.
1210 * e.g. png only needed
1212 * <masking>*.png</masking>
1214 * <control type="button" format="image">
1217 std::string ext
= pathSetting
->GetMasking(CServiceBroker::GetFileExtensionProvider());
1219 ext
= CServiceBroker::GetFileExtensionProvider().GetPictureExtensions();
1220 result
= CGUIDialogFileBrowser::ShowAndGetFile(shares
, ext
, heading
, path
, true);
1224 CGUIDialogFileBrowser::ShowAndGetDirectory(shares
, heading
, path
, pathSetting
->Writable());
1229 return pathSetting
->SetValue(path
);
1232 void CGUIControlButtonSetting::OnSliderChange(void* data
, CGUISliderControl
* slider
)
1237 std::string strText
;
1238 switch (m_pSetting
->GetType())
1240 case SettingType::Integer
:
1242 std::shared_ptr
<CSettingInt
> settingInt
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1243 if (settingInt
->SetValue(slider
->GetIntValue()))
1244 strText
= CGUIControlSliderSetting::GetText(m_pSetting
, settingInt
->GetValue(),
1245 settingInt
->GetMinimum(), settingInt
->GetStep(),
1246 settingInt
->GetMaximum(), m_localizer
);
1250 case SettingType::Number
:
1252 std::shared_ptr
<CSettingNumber
> settingNumber
=
1253 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1254 if (settingNumber
->SetValue(static_cast<double>(slider
->GetFloatValue())))
1255 strText
= CGUIControlSliderSetting::GetText(
1256 m_pSetting
, settingNumber
->GetValue(), settingNumber
->GetMinimum(),
1257 settingNumber
->GetStep(), settingNumber
->GetMaximum(), m_localizer
);
1265 if (!strText
.empty())
1266 slider
->SetTextValue(strText
);
1269 CGUIControlEditSetting::CGUIControlEditSetting(CGUIEditControl
* pEdit
,
1271 const std::shared_ptr
<CSetting
>& pSetting
,
1272 ILocalizer
* localizer
)
1273 : CGUIControlBaseSetting(id
, pSetting
, localizer
)
1275 std::shared_ptr
<const CSettingControlEdit
> control
=
1276 std::static_pointer_cast
<const CSettingControlEdit
>(pSetting
->GetControl());
1278 if (m_pEdit
== NULL
)
1282 int heading
= m_pSetting
->GetLabel();
1283 if (control
->GetHeading() > 0)
1284 heading
= control
->GetHeading();
1288 CGUIEditControl::INPUT_TYPE inputType
= CGUIEditControl::INPUT_TYPE_TEXT
;
1289 const std::string
& controlFormat
= control
->GetFormat();
1290 if (controlFormat
== "string")
1292 if (control
->IsHidden())
1293 inputType
= CGUIEditControl::INPUT_TYPE_PASSWORD
;
1295 else if (controlFormat
== "integer" || controlFormat
== "number")
1297 if (control
->VerifyNewValue())
1298 inputType
= CGUIEditControl::INPUT_TYPE_PASSWORD_NUMBER_VERIFY_NEW
;
1300 inputType
= CGUIEditControl::INPUT_TYPE_NUMBER
;
1302 else if (controlFormat
== "ip")
1303 inputType
= CGUIEditControl::INPUT_TYPE_IPADDRESS
;
1304 else if (controlFormat
== "md5")
1305 inputType
= CGUIEditControl::INPUT_TYPE_PASSWORD_MD5
;
1307 m_pEdit
->SetInputType(inputType
, heading
);
1309 // this will automatically trigger validation so it must be executed after
1310 // having set the value of the control based on the value of the setting
1311 m_pEdit
->SetInputValidation(InputValidation
, this);
1314 CGUIControlEditSetting::~CGUIControlEditSetting() = default;
1316 bool CGUIControlEditSetting::OnClick()
1318 if (m_pEdit
== NULL
)
1321 // update our string
1322 if (m_pSetting
->GetControl()->GetFormat() == "urlencoded")
1324 std::shared_ptr
<CSettingUrlEncodedString
> urlEncodedSetting
=
1325 std::static_pointer_cast
<CSettingUrlEncodedString
>(m_pSetting
);
1326 SetValid(urlEncodedSetting
->SetDecodedValue(m_pEdit
->GetLabel2()));
1329 SetValid(m_pSetting
->FromString(m_pEdit
->GetLabel2()));
1334 void CGUIControlEditSetting::Update(bool fromControl
, bool updateDisplayOnly
)
1336 if (fromControl
|| m_pEdit
== NULL
)
1339 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
1341 std::shared_ptr
<const CSettingControlEdit
> control
=
1342 std::static_pointer_cast
<const CSettingControlEdit
>(m_pSetting
->GetControl());
1344 if (control
->GetFormat() == "urlencoded")
1346 std::shared_ptr
<CSettingUrlEncodedString
> urlEncodedSetting
=
1347 std::static_pointer_cast
<CSettingUrlEncodedString
>(m_pSetting
);
1348 m_pEdit
->SetLabel2(urlEncodedSetting
->GetDecodedValue());
1351 m_pEdit
->SetLabel2(m_pSetting
->ToString());
1354 bool CGUIControlEditSetting::InputValidation(const std::string
& input
, void* data
)
1359 CGUIControlEditSetting
* editControl
= reinterpret_cast<CGUIControlEditSetting
*>(data
);
1360 if (editControl
->GetSetting() == NULL
)
1363 editControl
->SetValid(editControl
->GetSetting()->CheckValidity(input
));
1364 return editControl
->IsValid();
1367 CGUIControlSliderSetting::CGUIControlSliderSetting(CGUISettingsSliderControl
* pSlider
,
1369 std::shared_ptr
<CSetting
> pSetting
,
1370 ILocalizer
* localizer
)
1371 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
1373 m_pSlider
= pSlider
;
1374 if (m_pSlider
== NULL
)
1377 m_pSlider
->SetID(id
);
1379 switch (m_pSetting
->GetType())
1381 case SettingType::Integer
:
1383 std::shared_ptr
<CSettingInt
> settingInt
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1384 if (m_pSetting
->GetControl()->GetFormat() == "percentage")
1385 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_PERCENTAGE
);
1388 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_INT
);
1389 m_pSlider
->SetRange(settingInt
->GetMinimum(), settingInt
->GetMaximum());
1391 m_pSlider
->SetIntInterval(settingInt
->GetStep());
1395 case SettingType::Number
:
1397 std::shared_ptr
<CSettingNumber
> settingNumber
=
1398 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1399 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_FLOAT
);
1400 m_pSlider
->SetFloatRange(static_cast<float>(settingNumber
->GetMinimum()),
1401 static_cast<float>(settingNumber
->GetMaximum()));
1402 m_pSlider
->SetFloatInterval(static_cast<float>(settingNumber
->GetStep()));
1411 CGUIControlSliderSetting::~CGUIControlSliderSetting() = default;
1413 bool CGUIControlSliderSetting::OnClick()
1415 if (m_pSlider
== NULL
)
1418 switch (m_pSetting
->GetType())
1420 case SettingType::Integer
:
1422 std::static_pointer_cast
<CSettingInt
>(m_pSetting
)->SetValue(m_pSlider
->GetIntValue()));
1425 case SettingType::Number
:
1426 SetValid(std::static_pointer_cast
<CSettingNumber
>(m_pSetting
)
1427 ->SetValue(static_cast<double>(m_pSlider
->GetFloatValue())));
1437 void CGUIControlSliderSetting::Update(bool fromControl
, bool updateDisplayOnly
)
1439 if (m_pSlider
== NULL
)
1442 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
1444 std::string strText
;
1445 switch (m_pSetting
->GetType())
1447 case SettingType::Integer
:
1449 std::shared_ptr
<const CSettingInt
> settingInt
=
1450 std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1453 value
= m_pSlider
->GetIntValue();
1456 value
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
)->GetValue();
1457 m_pSlider
->SetIntValue(value
);
1460 strText
= CGUIControlSliderSetting::GetText(m_pSetting
, value
, settingInt
->GetMinimum(),
1461 settingInt
->GetStep(), settingInt
->GetMaximum(),
1466 case SettingType::Number
:
1468 std::shared_ptr
<const CSettingNumber
> settingNumber
=
1469 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1472 value
= static_cast<double>(m_pSlider
->GetFloatValue());
1475 value
= std::static_pointer_cast
<CSettingNumber
>(m_pSetting
)->GetValue();
1476 m_pSlider
->SetFloatValue((float)value
);
1479 strText
= CGUIControlSliderSetting::GetText(m_pSetting
, value
, settingNumber
->GetMinimum(),
1480 settingNumber
->GetStep(),
1481 settingNumber
->GetMaximum(), m_localizer
);
1489 if (!strText
.empty())
1490 m_pSlider
->SetTextValue(strText
);
1493 std::string
CGUIControlSliderSetting::GetText(const std::shared_ptr
<CSetting
>& setting
,
1494 const CVariant
& value
,
1495 const CVariant
& minimum
,
1496 const CVariant
& step
,
1497 const CVariant
& maximum
,
1498 ILocalizer
* localizer
)
1500 if (setting
== NULL
|| !(value
.isInteger() || value
.isDouble()))
1503 const auto control
= std::static_pointer_cast
<const CSettingControlSlider
>(setting
->GetControl());
1504 if (control
== NULL
)
1507 SettingControlSliderFormatter formatter
= control
->GetFormatter();
1508 if (formatter
!= NULL
)
1509 return formatter(control
, value
, minimum
, step
, maximum
);
1511 std::string formatString
= control
->GetFormatString();
1512 if (control
->GetFormatLabel() > -1)
1513 formatString
= ::Localize(control
->GetFormatLabel(), localizer
);
1515 std::string formattedString
;
1516 if (FormatText(formatString
, value
, setting
->GetId(), formattedString
))
1517 return formattedString
;
1519 // fall back to default formatting
1520 formatString
= control
->GetDefaultFormatString();
1521 if (FormatText(formatString
, value
, setting
->GetId(), formattedString
))
1522 return formattedString
;
1527 bool CGUIControlSliderSetting::FormatText(const std::string
& formatString
,
1528 const CVariant
& value
,
1529 const std::string
& settingId
,
1530 std::string
& formattedText
)
1534 if (value
.isDouble())
1535 formattedText
= StringUtils::Format(formatString
, value
.asDouble());
1537 formattedText
= StringUtils::Format(formatString
, static_cast<int>(value
.asInteger()));
1539 catch (const std::runtime_error
& err
)
1541 CLog::Log(LOGERROR
, "Invalid formatting with string \"{}\" for setting \"{}\": {}",
1542 formatString
, settingId
, err
.what());
1549 CGUIControlRangeSetting::CGUIControlRangeSetting(CGUISettingsSliderControl
* pSlider
,
1551 std::shared_ptr
<CSetting
> pSetting
,
1552 ILocalizer
* localizer
)
1553 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
1555 m_pSlider
= pSlider
;
1556 if (m_pSlider
== NULL
)
1559 m_pSlider
->SetID(id
);
1560 m_pSlider
->SetRangeSelection(true);
1562 if (m_pSetting
->GetType() == SettingType::List
)
1564 std::shared_ptr
<CSettingList
> settingList
= std::static_pointer_cast
<CSettingList
>(m_pSetting
);
1565 SettingConstPtr listDefintion
= settingList
->GetDefinition();
1566 switch (listDefintion
->GetType())
1568 case SettingType::Integer
:
1570 std::shared_ptr
<const CSettingInt
> listDefintionInt
=
1571 std::static_pointer_cast
<const CSettingInt
>(listDefintion
);
1572 if (m_pSetting
->GetControl()->GetFormat() == "percentage")
1573 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_PERCENTAGE
);
1576 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_INT
);
1577 m_pSlider
->SetRange(listDefintionInt
->GetMinimum(), listDefintionInt
->GetMaximum());
1579 m_pSlider
->SetIntInterval(listDefintionInt
->GetStep());
1583 case SettingType::Number
:
1585 std::shared_ptr
<const CSettingNumber
> listDefinitionNumber
=
1586 std::static_pointer_cast
<const CSettingNumber
>(listDefintion
);
1587 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_FLOAT
);
1588 m_pSlider
->SetFloatRange(static_cast<float>(listDefinitionNumber
->GetMinimum()),
1589 static_cast<float>(listDefinitionNumber
->GetMaximum()));
1590 m_pSlider
->SetFloatInterval(static_cast<float>(listDefinitionNumber
->GetStep()));
1600 CGUIControlRangeSetting::~CGUIControlRangeSetting() = default;
1602 bool CGUIControlRangeSetting::OnClick()
1604 if (m_pSlider
== NULL
|| m_pSetting
->GetType() != SettingType::List
)
1607 std::shared_ptr
<CSettingList
> settingList
= std::static_pointer_cast
<CSettingList
>(m_pSetting
);
1608 const SettingList
& settingListValues
= settingList
->GetValue();
1609 if (settingListValues
.size() != 2)
1612 std::vector
<CVariant
> values
;
1613 SettingConstPtr listDefintion
= settingList
->GetDefinition();
1614 switch (listDefintion
->GetType())
1616 case SettingType::Integer
:
1617 values
.emplace_back(m_pSlider
->GetIntValue(CGUISliderControl::RangeSelectorLower
));
1618 values
.emplace_back(m_pSlider
->GetIntValue(CGUISliderControl::RangeSelectorUpper
));
1621 case SettingType::Number
:
1622 values
.emplace_back(m_pSlider
->GetFloatValue(CGUISliderControl::RangeSelectorLower
));
1623 values
.emplace_back(m_pSlider
->GetFloatValue(CGUISliderControl::RangeSelectorUpper
));
1630 if (values
.size() != 2)
1633 SetValid(CSettingUtils::SetList(settingList
, values
));
1637 void CGUIControlRangeSetting::Update(bool fromControl
, bool updateDisplayOnly
)
1639 if (m_pSlider
== NULL
|| m_pSetting
->GetType() != SettingType::List
)
1642 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
1644 std::shared_ptr
<CSettingList
> settingList
= std::static_pointer_cast
<CSettingList
>(m_pSetting
);
1645 const SettingList
& settingListValues
= settingList
->GetValue();
1646 if (settingListValues
.size() != 2)
1649 SettingConstPtr listDefintion
= settingList
->GetDefinition();
1650 std::shared_ptr
<const CSettingControlRange
> controlRange
=
1651 std::static_pointer_cast
<const CSettingControlRange
>(m_pSetting
->GetControl());
1652 const std::string
& controlFormat
= controlRange
->GetFormat();
1654 std::string strText
;
1655 std::string strTextLower
, strTextUpper
;
1656 std::string formatString
=
1657 Localize(controlRange
->GetFormatLabel() > -1 ? controlRange
->GetFormatLabel() : 21469);
1658 std::string valueFormat
= controlRange
->GetValueFormat();
1659 if (controlRange
->GetValueFormatLabel() > -1)
1660 valueFormat
= Localize(controlRange
->GetValueFormatLabel());
1662 switch (listDefintion
->GetType())
1664 case SettingType::Integer
:
1666 int valueLower
, valueUpper
;
1669 valueLower
= m_pSlider
->GetIntValue(CGUISliderControl::RangeSelectorLower
);
1670 valueUpper
= m_pSlider
->GetIntValue(CGUISliderControl::RangeSelectorUpper
);
1674 valueLower
= std::static_pointer_cast
<CSettingInt
>(settingListValues
[0])->GetValue();
1675 valueUpper
= std::static_pointer_cast
<CSettingInt
>(settingListValues
[1])->GetValue();
1676 m_pSlider
->SetIntValue(valueLower
, CGUISliderControl::RangeSelectorLower
);
1677 m_pSlider
->SetIntValue(valueUpper
, CGUISliderControl::RangeSelectorUpper
);
1680 if (controlFormat
== "date" || controlFormat
== "time")
1682 CDateTime
dateLower((time_t)valueLower
);
1683 CDateTime
dateUpper((time_t)valueUpper
);
1685 if (controlFormat
== "date")
1687 if (valueFormat
.empty())
1689 strTextLower
= dateLower
.GetAsLocalizedDate();
1690 strTextUpper
= dateUpper
.GetAsLocalizedDate();
1694 strTextLower
= dateLower
.GetAsLocalizedDate(valueFormat
);
1695 strTextUpper
= dateUpper
.GetAsLocalizedDate(valueFormat
);
1700 if (valueFormat
.empty())
1701 valueFormat
= "mm:ss";
1703 strTextLower
= dateLower
.GetAsLocalizedTime(valueFormat
);
1704 strTextUpper
= dateUpper
.GetAsLocalizedTime(valueFormat
);
1709 strTextLower
= StringUtils::Format(valueFormat
, valueLower
);
1710 strTextUpper
= StringUtils::Format(valueFormat
, valueUpper
);
1713 if (valueLower
!= valueUpper
)
1714 strText
= StringUtils::Format(formatString
, strTextLower
, strTextUpper
);
1716 strText
= strTextLower
;
1720 case SettingType::Number
:
1722 double valueLower
, valueUpper
;
1726 static_cast<double>(m_pSlider
->GetFloatValue(CGUISliderControl::RangeSelectorLower
));
1728 static_cast<double>(m_pSlider
->GetFloatValue(CGUISliderControl::RangeSelectorUpper
));
1732 valueLower
= std::static_pointer_cast
<CSettingNumber
>(settingListValues
[0])->GetValue();
1733 valueUpper
= std::static_pointer_cast
<CSettingNumber
>(settingListValues
[1])->GetValue();
1734 m_pSlider
->SetFloatValue((float)valueLower
, CGUISliderControl::RangeSelectorLower
);
1735 m_pSlider
->SetFloatValue((float)valueUpper
, CGUISliderControl::RangeSelectorUpper
);
1738 strTextLower
= StringUtils::Format(valueFormat
, valueLower
);
1739 if (valueLower
!= valueUpper
)
1741 strTextUpper
= StringUtils::Format(valueFormat
, valueUpper
);
1742 strText
= StringUtils::Format(formatString
, strTextLower
, strTextUpper
);
1745 strText
= strTextLower
;
1754 if (!strText
.empty())
1755 m_pSlider
->SetTextValue(strText
);
1758 CGUIControlSeparatorSetting::CGUIControlSeparatorSetting(CGUIImage
* pImage
,
1760 ILocalizer
* localizer
)
1761 : CGUIControlBaseSetting(id
, NULL
, localizer
)
1764 if (m_pImage
== NULL
)
1767 m_pImage
->SetID(id
);
1770 CGUIControlSeparatorSetting::~CGUIControlSeparatorSetting() = default;
1772 CGUIControlGroupTitleSetting::CGUIControlGroupTitleSetting(CGUILabelControl
* pLabel
,
1774 ILocalizer
* localizer
)
1775 : CGUIControlBaseSetting(id
, NULL
, localizer
)
1778 if (m_pLabel
== NULL
)
1781 m_pLabel
->SetID(id
);
1784 CGUIControlGroupTitleSetting::~CGUIControlGroupTitleSetting() = default;
1786 CGUIControlLabelSetting::CGUIControlLabelSetting(CGUIButtonControl
* pButton
,
1788 std::shared_ptr
<CSetting
> pSetting
,
1789 ILocalizer
* localizer
)
1790 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
1792 m_pButton
= pButton
;
1793 if (m_pButton
== NULL
)
1796 m_pButton
->SetID(id
);
1797 UpdateFromSetting();