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 "FileItemList.h"
13 #include "ServiceBroker.h"
15 #include "addons/AddonManager.h"
16 #include "addons/gui/GUIWindowAddonBrowser.h"
17 #include "addons/settings/SettingUrlEncodedString.h"
18 #include "dialogs/GUIDialogColorPicker.h"
19 #include "dialogs/GUIDialogFileBrowser.h"
20 #include "dialogs/GUIDialogNumeric.h"
21 #include "dialogs/GUIDialogSelect.h"
22 #include "dialogs/GUIDialogSlider.h"
23 #include "guilib/GUIColorButtonControl.h"
24 #include "guilib/GUIComponent.h"
25 #include "guilib/GUIEditControl.h"
26 #include "guilib/GUIImage.h"
27 #include "guilib/GUIKeyboardFactory.h"
28 #include "guilib/GUILabelControl.h"
29 #include "guilib/GUIRadioButtonControl.h"
30 #include "guilib/GUISettingsSliderControl.h"
31 #include "guilib/GUISpinControlEx.h"
32 #include "guilib/GUIWindowManager.h"
33 #include "guilib/LocalizeStrings.h"
34 #include "settings/MediaSourceSettings.h"
35 #include "settings/SettingAddon.h"
36 #include "settings/SettingControl.h"
37 #include "settings/SettingDateTime.h"
38 #include "settings/SettingPath.h"
39 #include "settings/SettingUtils.h"
40 #include "settings/lib/Setting.h"
41 #include "settings/lib/SettingDefinitions.h"
42 #include "storage/MediaManager.h"
43 #include "utils/FileExtensionProvider.h"
44 #include "utils/StringUtils.h"
45 #include "utils/Variant.h"
46 #include "utils/log.h"
51 using namespace ADDON
;
53 static std::string
Localize(std::uint32_t code
,
54 ILocalizer
* localizer
,
55 const std::string
& addonId
= "")
57 if (localizer
== nullptr)
62 std::string label
= g_localizeStrings
.GetAddonString(addonId
, code
);
67 return localizer
->Localize(code
);
70 template<typename TValueType
>
71 static CFileItemPtr
GetFileItem(const std::string
& label
,
72 const std::string
& label2
,
73 const TValueType
& value
,
74 const std::vector
<std::pair
<std::string
, CVariant
>>& properties
,
75 const std::set
<TValueType
>& selectedValues
)
77 CFileItemPtr
item(new CFileItem(label
));
78 item
->SetProperty("value", value
);
79 item
->SetLabel2(label2
);
81 for (const auto& prop
: properties
)
82 item
->SetProperty(prop
.first
, prop
.second
);
84 if (selectedValues
.find(value
) != selectedValues
.end())
90 template<class SettingOption
>
91 static bool CompareSettingOptionAseconding(const SettingOption
& lhs
, const SettingOption
& rhs
)
93 return StringUtils::CompareNoCase(lhs
.label
, rhs
.label
) < 0;
96 template<class SettingOption
>
97 static bool CompareSettingOptionDeseconding(const SettingOption
& lhs
, const SettingOption
& rhs
)
99 return StringUtils::CompareNoCase(lhs
.label
, rhs
.label
) > 0;
102 static bool GetIntegerOptions(const SettingConstPtr
& setting
,
103 IntegerSettingOptions
& options
,
104 std::set
<int>& selectedOptions
,
105 ILocalizer
* localizer
,
108 std::shared_ptr
<const CSettingInt
> pSettingInt
= NULL
;
109 if (setting
->GetType() == SettingType::Integer
)
110 pSettingInt
= std::static_pointer_cast
<const CSettingInt
>(setting
);
111 else if (setting
->GetType() == SettingType::List
)
113 std::shared_ptr
<const CSettingList
> settingList
=
114 std::static_pointer_cast
<const CSettingList
>(setting
);
115 if (settingList
->GetElementType() != SettingType::Integer
)
118 pSettingInt
= std::static_pointer_cast
<const CSettingInt
>(settingList
->GetDefinition());
121 switch (pSettingInt
->GetOptionsType())
123 case SettingOptionsType::StaticTranslatable
:
125 const TranslatableIntegerSettingOptions
& settingOptions
=
126 pSettingInt
->GetTranslatableOptions();
127 for (const auto& option
: settingOptions
)
128 options
.emplace_back(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
.emplace_back(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
.emplace_back(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
)
298 : m_id(id
), m_pSetting(std::move(pSetting
)), m_localizer(localizer
)
302 bool CGUIControlBaseSetting::IsEnabled() const
304 return m_pSetting
!= NULL
&& m_pSetting
->IsEnabled();
307 void CGUIControlBaseSetting::UpdateFromControl()
312 void CGUIControlBaseSetting::UpdateFromSetting(bool updateDisplayOnly
/* = false */)
314 Update(false, updateDisplayOnly
);
317 std::string
CGUIControlBaseSetting::Localize(std::uint32_t code
) const
319 return ::Localize(code
, m_localizer
);
322 void CGUIControlBaseSetting::Update(bool fromControl
, bool updateDisplayOnly
)
324 if (fromControl
|| updateDisplayOnly
)
327 CGUIControl
* control
= GetControl();
331 control
->SetEnabled(IsEnabled());
333 control
->SetVisible(m_pSetting
->IsVisible());
337 CGUIControlRadioButtonSetting::CGUIControlRadioButtonSetting(CGUIRadioButtonControl
* pRadioButton
,
339 std::shared_ptr
<CSetting
> pSetting
,
340 ILocalizer
* localizer
)
341 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
343 m_pRadioButton
= pRadioButton
;
344 if (m_pRadioButton
== NULL
)
347 m_pRadioButton
->SetID(id
);
350 CGUIControlRadioButtonSetting::~CGUIControlRadioButtonSetting() = default;
352 bool CGUIControlRadioButtonSetting::OnClick()
354 SetValid(std::static_pointer_cast
<CSettingBool
>(m_pSetting
)
355 ->SetValue(!std::static_pointer_cast
<CSettingBool
>(m_pSetting
)->GetValue()));
359 void CGUIControlRadioButtonSetting::Update(bool fromControl
, bool updateDisplayOnly
)
361 if (fromControl
|| m_pRadioButton
== NULL
)
364 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
366 m_pRadioButton
->SetSelected(std::static_pointer_cast
<CSettingBool
>(m_pSetting
)->GetValue());
369 CGUIControlColorButtonSetting::CGUIControlColorButtonSetting(
370 CGUIColorButtonControl
* pColorControl
,
372 const std::shared_ptr
<CSetting
>& pSetting
,
373 ILocalizer
* localizer
)
374 : CGUIControlBaseSetting(id
, pSetting
, localizer
)
376 m_pColorButton
= pColorControl
;
380 m_pColorButton
->SetID(id
);
383 CGUIControlColorButtonSetting::~CGUIControlColorButtonSetting() = default;
385 bool CGUIControlColorButtonSetting::OnClick()
390 std::shared_ptr
<CSettingString
> settingHexColor
=
391 std::static_pointer_cast
<CSettingString
>(m_pSetting
);
393 CGUIDialogColorPicker
* dialog
=
394 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogColorPicker
>(
395 WINDOW_DIALOG_COLOR_PICKER
);
400 dialog
->SetHeading(CVariant
{Localize(m_pSetting
->GetLabel())});
401 dialog
->LoadColors();
402 std::string hexColor
;
404 hexColor
= settingHexColor
.get()->GetValue();
405 dialog
->SetSelectedColor(hexColor
);
408 if (!dialog
->IsConfirmed())
412 std::static_pointer_cast
<CSettingString
>(m_pSetting
)->SetValue(dialog
->GetSelectedColor()));
416 void CGUIControlColorButtonSetting::Update(bool fromControl
, bool updateDisplayOnly
)
418 if (fromControl
|| !m_pColorButton
)
421 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
422 // Set the color to apply to the preview color box
423 m_pColorButton
->SetImageBoxColor(
424 std::static_pointer_cast
<CSettingString
>(m_pSetting
)->GetValue());
427 CGUIControlSpinExSetting::CGUIControlSpinExSetting(CGUISpinControlEx
* pSpin
,
429 std::shared_ptr
<CSetting
> pSetting
,
430 ILocalizer
* localizer
)
431 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
439 const std::string
& controlFormat
= m_pSetting
->GetControl()->GetFormat();
440 if (controlFormat
== "number")
442 std::shared_ptr
<CSettingNumber
> pSettingNumber
=
443 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
444 m_pSpin
->SetType(SPIN_CONTROL_TYPE_FLOAT
);
445 m_pSpin
->SetFloatRange(static_cast<float>(pSettingNumber
->GetMinimum()),
446 static_cast<float>(pSettingNumber
->GetMaximum()));
447 m_pSpin
->SetFloatInterval(static_cast<float>(pSettingNumber
->GetStep()));
449 else if (controlFormat
== "integer")
450 m_pSpin
->SetType(SPIN_CONTROL_TYPE_TEXT
);
451 else if (controlFormat
== "string")
453 m_pSpin
->SetType(SPIN_CONTROL_TYPE_TEXT
);
455 if (m_pSetting
->GetType() == SettingType::Integer
)
456 FillIntegerSettingControl(false);
457 else if (m_pSetting
->GetType() == SettingType::Number
)
459 std::shared_ptr
<CSettingNumber
> pSettingNumber
=
460 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
461 std::shared_ptr
<const CSettingControlFormattedRange
> control
=
462 std::static_pointer_cast
<const CSettingControlFormattedRange
>(m_pSetting
->GetControl());
464 for (double value
= pSettingNumber
->GetMinimum(); value
<= pSettingNumber
->GetMaximum();
465 value
+= pSettingNumber
->GetStep(), index
++)
467 std::string strLabel
;
468 if (value
== pSettingNumber
->GetMinimum() && control
->GetMinimumLabel() > -1)
469 strLabel
= Localize(control
->GetMinimumLabel());
470 else if (control
->GetFormatLabel() > -1)
471 strLabel
= StringUtils::Format(Localize(control
->GetFormatLabel()), value
);
473 strLabel
= StringUtils::Format(control
->GetFormatString(), value
);
475 m_pSpin
->AddLabel(strLabel
, index
);
481 CGUIControlSpinExSetting::~CGUIControlSpinExSetting() = default;
483 bool CGUIControlSpinExSetting::OnClick()
488 switch (m_pSetting
->GetType())
490 case SettingType::Integer
:
491 SetValid(std::static_pointer_cast
<CSettingInt
>(m_pSetting
)->SetValue(m_pSpin
->GetValue()));
494 case SettingType::Number
:
496 auto pSettingNumber
= std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
497 const auto& controlFormat
= m_pSetting
->GetControl()->GetFormat();
498 if (controlFormat
== "number")
499 SetValid(pSettingNumber
->SetValue(static_cast<double>(m_pSpin
->GetFloatValue())));
501 SetValid(pSettingNumber
->SetValue(pSettingNumber
->GetMinimum() +
502 pSettingNumber
->GetStep() * m_pSpin
->GetValue()));
507 case SettingType::String
:
508 SetValid(std::static_pointer_cast
<CSettingString
>(m_pSetting
)
509 ->SetValue(m_pSpin
->GetStringValue()));
519 void CGUIControlSpinExSetting::Update(bool fromControl
, bool updateDisplayOnly
)
521 if (fromControl
|| m_pSpin
== NULL
)
524 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
526 FillControl(!updateDisplayOnly
);
528 if (!updateDisplayOnly
)
530 // disable the spinner if it has less than two items
531 if (!m_pSpin
->IsDisabled() && (m_pSpin
->GetMaximum() - m_pSpin
->GetMinimum()) == 0)
532 m_pSpin
->SetEnabled(false);
536 void CGUIControlSpinExSetting::FillControl(bool updateValues
)
544 const std::string
& controlFormat
= m_pSetting
->GetControl()->GetFormat();
545 if (controlFormat
== "number")
547 std::shared_ptr
<CSettingNumber
> pSettingNumber
=
548 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
549 m_pSpin
->SetFloatValue((float)pSettingNumber
->GetValue());
551 else if (controlFormat
== "integer")
552 FillIntegerSettingControl(updateValues
);
553 else if (controlFormat
== "string")
555 if (m_pSetting
->GetType() == SettingType::Integer
)
556 FillIntegerSettingControl(updateValues
);
557 else if (m_pSetting
->GetType() == SettingType::Number
)
558 FillFloatSettingControl();
559 else if (m_pSetting
->GetType() == SettingType::String
)
560 FillStringSettingControl(updateValues
);
564 void CGUIControlSpinExSetting::FillIntegerSettingControl(bool updateValues
)
566 IntegerSettingOptions options
;
567 std::set
<int> selectedValues
;
568 // get the integer options
569 if (!GetIntegerOptions(m_pSetting
, options
, selectedValues
, m_localizer
, updateValues
) ||
570 selectedValues
.size() != 1)
575 // add them to the spinner
576 for (const auto& option
: options
)
577 m_pSpin
->AddLabel(option
.label
, option
.value
);
580 // and set the current value
581 m_pSpin
->SetValue(*selectedValues
.begin());
584 void CGUIControlSpinExSetting::FillFloatSettingControl()
586 std::shared_ptr
<CSettingNumber
> pSettingNumber
=
587 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
588 std::shared_ptr
<const CSettingControlFormattedRange
> control
=
589 std::static_pointer_cast
<const CSettingControlFormattedRange
>(m_pSetting
->GetControl());
591 int currentIndex
= 0;
592 for (double value
= pSettingNumber
->GetMinimum(); value
<= pSettingNumber
->GetMaximum();
593 value
+= pSettingNumber
->GetStep(), index
++)
595 if (value
== pSettingNumber
->GetValue())
597 currentIndex
= index
;
602 m_pSpin
->SetValue(currentIndex
);
605 void CGUIControlSpinExSetting::FillStringSettingControl(bool updateValues
)
607 StringSettingOptions options
;
608 std::set
<std::string
> selectedValues
;
609 // get the string options
610 if (!GetStringOptions(m_pSetting
, options
, selectedValues
, m_localizer
, updateValues
) ||
611 selectedValues
.size() != 1)
616 // add them to the spinner
617 for (const auto& option
: options
)
618 m_pSpin
->AddLabel(option
.label
, option
.value
);
621 // and set the current value
622 m_pSpin
->SetStringValue(*selectedValues
.begin());
625 CGUIControlListSetting::CGUIControlListSetting(CGUIButtonControl
* pButton
,
627 std::shared_ptr
<CSetting
> pSetting
,
628 ILocalizer
* localizer
)
629 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
632 if (m_pButton
== NULL
)
635 m_pButton
->SetID(id
);
638 CGUIControlListSetting::~CGUIControlListSetting() = default;
640 bool CGUIControlListSetting::OnClick()
642 if (m_pButton
== NULL
)
645 CGUIDialogSelect
* dialog
=
646 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogSelect
>(
647 WINDOW_DIALOG_SELECT
);
651 CFileItemList options
;
652 std::shared_ptr
<const CSettingControlList
> control
=
653 std::static_pointer_cast
<const CSettingControlList
>(m_pSetting
->GetControl());
654 bool optionsValid
= GetItems(m_pSetting
, options
, false);
656 bool bValueAdded
= false;
657 bool bAllowNewOption
= false;
658 if (m_pSetting
->GetType() == SettingType::List
)
660 std::shared_ptr
<const CSettingList
> settingList
=
661 std::static_pointer_cast
<const CSettingList
>(m_pSetting
);
662 if (settingList
->GetElementType() == SettingType::String
)
664 bAllowNewOption
= std::static_pointer_cast
<const CSettingString
>(settingList
->GetDefinition())
668 if (!bAllowNewOption
)
670 // Do not show dialog if
671 // there are no items to be chosen
672 if (!optionsValid
|| options
.Size() <= 0)
676 dialog
->SetHeading(CVariant
{Localize(m_pSetting
->GetLabel())});
677 dialog
->SetItems(options
);
678 dialog
->SetMultiSelection(control
->CanMultiSelect());
679 dialog
->SetUseDetails(control
->UseDetails());
682 if (!dialog
->IsConfirmed())
687 // Possible to add items, as well as select from any options given
688 // Add any current values that are not options as items in list
689 std::vector
<CVariant
> list
=
690 CSettingUtils::GetList(std::static_pointer_cast
<const CSettingList
>(m_pSetting
));
691 for (const auto& value
: list
)
693 bool found
= std::any_of(options
.begin(), options
.end(), [&](const auto& p
) {
694 return p
->GetProperty("value").asString() == value
.asString();
698 CFileItemPtr
item(new CFileItem(value
.asString()));
699 item
->SetProperty("value", value
.asString());
708 std::string strAddButton
= Localize(control
->GetAddButtonLabel());
709 if (strAddButton
.empty())
710 strAddButton
= Localize(15019); // "ADD"
711 dialog
->Reset(); // Clears AddButtonPressed
712 dialog
->SetHeading(CVariant
{ Localize(m_pSetting
->GetLabel()) });
713 dialog
->SetItems(options
);
714 dialog
->SetMultiSelection(control
->CanMultiSelect());
715 dialog
->EnableButton2(bAllowNewOption
, strAddButton
);
719 if (!dialog
->IsConfirmed())
722 if (dialog
->IsButton2Pressed())
724 // Get new list value
725 std::string strLabel
;
726 bool bValidType
= false;
727 while (!bValidType
&& CGUIKeyboardFactory::ShowAndGetInput(
728 strLabel
, CVariant
{ Localize(control
->GetAddButtonLabel()) }, false))
730 // Validate new value is unique and truncate at any comma
731 StringUtils::Trim(strLabel
);
732 strLabel
= strLabel
.substr(0, strLabel
.find(','));
733 if (!strLabel
.empty())
735 bValidType
= !std::any_of(options
.begin(), options
.end(), [&](const auto& p
) {
736 return p
->GetProperty("value").asString() == strLabel
;
740 { // Add new value to the list of options
741 CFileItemPtr
pItem(new CFileItem(strLabel
));
743 pItem
->SetProperty("value", strLabel
);
749 bRepeat
= dialog
->IsButton2Pressed();
753 std::vector
<CVariant
> values
;
754 for (int i
: dialog
->GetSelectedItems())
756 const CFileItemPtr item
= options
.Get(i
);
757 if (item
== NULL
|| !item
->HasProperty("value"))
760 values
.push_back(item
->GetProperty("value"));
764 switch (m_pSetting
->GetType())
766 case SettingType::Integer
:
767 if (values
.size() > 1)
769 ret
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
)
770 ->SetValue((int)values
.at(0).asInteger());
773 case SettingType::String
:
774 if (values
.size() > 1)
776 ret
= std::static_pointer_cast
<CSettingString
>(m_pSetting
)->SetValue(values
.at(0).asString());
779 case SettingType::List
:
780 ret
= CSettingUtils::SetList(std::static_pointer_cast
<CSettingList
>(m_pSetting
), values
);
788 UpdateFromSetting(!bValueAdded
);
795 void CGUIControlListSetting::Update(bool fromControl
, bool updateDisplayOnly
)
797 if (fromControl
|| m_pButton
== NULL
)
800 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
802 CFileItemList options
;
803 std::shared_ptr
<const CSettingControlList
> control
=
804 std::static_pointer_cast
<const CSettingControlList
>(m_pSetting
->GetControl());
805 bool optionsValid
= GetItems(m_pSetting
, options
, !updateDisplayOnly
);
807 bool bAllowNewOption
= false;
808 if (m_pSetting
->GetType() == SettingType::List
)
810 std::shared_ptr
<const CSettingList
> settingList
=
811 std::static_pointer_cast
<const CSettingList
>(m_pSetting
);
812 if (settingList
->GetElementType() == SettingType::String
)
814 bAllowNewOption
= std::static_pointer_cast
<const CSettingString
>(settingList
->GetDefinition())
820 if (optionsValid
&& !control
->HideValue())
822 SettingControlListValueFormatter formatter
= control
->GetFormatter();
824 label2
= formatter(m_pSetting
);
826 if (label2
.empty() && bAllowNewOption
)
828 const std::shared_ptr
<const CSettingList
> settingList
=
829 std::static_pointer_cast
<const CSettingList
>(m_pSetting
);
830 label2
= settingList
->ToString();
835 std::vector
<std::string
> labels
;
836 for (int index
= 0; index
< options
.Size(); index
++)
838 const CFileItemPtr pItem
= options
.Get(index
);
839 if (pItem
->IsSelected())
840 labels
.push_back(pItem
->GetLabel());
843 label2
= StringUtils::Join(labels
, ", ");
847 m_pButton
->SetLabel2(label2
);
849 if (!updateDisplayOnly
)
851 // Disable the control if no items can be added and
852 // there are no items to be chosen
853 if (!m_pButton
->IsDisabled() && !bAllowNewOption
&& (options
.Size() <= 0))
854 m_pButton
->SetEnabled(false);
858 bool CGUIControlListSetting::GetItems(const SettingConstPtr
& setting
,
859 CFileItemList
& items
,
860 bool updateItems
) const
862 std::shared_ptr
<const CSettingControlList
> control
=
863 std::static_pointer_cast
<const CSettingControlList
>(setting
->GetControl());
864 const std::string
& controlFormat
= control
->GetFormat();
866 if (controlFormat
== "integer")
867 return GetIntegerItems(setting
, items
, updateItems
);
868 else if (controlFormat
== "string")
870 if (setting
->GetType() == SettingType::Integer
||
871 (setting
->GetType() == SettingType::List
&&
872 std::static_pointer_cast
<const CSettingList
>(setting
)->GetElementType() ==
873 SettingType::Integer
))
874 return GetIntegerItems(setting
, items
, updateItems
);
875 else if (setting
->GetType() == SettingType::String
||
876 (setting
->GetType() == SettingType::List
&&
877 std::static_pointer_cast
<const CSettingList
>(setting
)->GetElementType() ==
878 SettingType::String
))
879 return GetStringItems(setting
, items
, updateItems
);
887 bool CGUIControlListSetting::GetIntegerItems(const SettingConstPtr
& setting
,
888 CFileItemList
& items
,
889 bool updateItems
) const
891 IntegerSettingOptions options
;
892 std::set
<int> selectedValues
;
893 // get the integer options
894 if (!GetIntegerOptions(setting
, options
, selectedValues
, m_localizer
, updateItems
))
897 // turn them into CFileItems and add them to the item list
898 for (const auto& option
: options
)
900 GetFileItem(option
.label
, option
.label2
, option
.value
, option
.properties
, selectedValues
));
905 bool CGUIControlListSetting::GetStringItems(const SettingConstPtr
& setting
,
906 CFileItemList
& items
,
907 bool updateItems
) const
909 StringSettingOptions options
;
910 std::set
<std::string
> selectedValues
;
911 // get the string options
912 if (!GetStringOptions(setting
, options
, selectedValues
, m_localizer
, updateItems
))
915 // turn them into CFileItems and add them to the item list
916 for (const auto& option
: options
)
918 GetFileItem(option
.label
, option
.label2
, option
.value
, option
.properties
, selectedValues
));
923 CGUIControlButtonSetting::CGUIControlButtonSetting(CGUIButtonControl
* pButton
,
925 std::shared_ptr
<CSetting
> pSetting
,
926 ILocalizer
* localizer
)
927 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
930 if (m_pButton
== NULL
)
933 m_pButton
->SetID(id
);
936 CGUIControlButtonSetting::~CGUIControlButtonSetting() = default;
938 bool CGUIControlButtonSetting::OnClick()
940 if (m_pButton
== NULL
)
943 std::shared_ptr
<const ISettingControl
> control
= m_pSetting
->GetControl();
944 const std::string
& controlType
= control
->GetType();
945 const std::string
& controlFormat
= control
->GetFormat();
946 if (controlType
== "button")
948 std::shared_ptr
<const CSettingControlButton
> buttonControl
=
949 std::static_pointer_cast
<const CSettingControlButton
>(control
);
950 if (controlFormat
== "addon")
952 // prompt for the addon
953 std::shared_ptr
<CSettingAddon
> setting
;
954 std::vector
<std::string
> addonIDs
;
955 if (m_pSetting
->GetType() == SettingType::List
)
957 std::shared_ptr
<CSettingList
> settingList
=
958 std::static_pointer_cast
<CSettingList
>(m_pSetting
);
959 setting
= std::static_pointer_cast
<CSettingAddon
>(settingList
->GetDefinition());
960 for (const SettingPtr
& addon
: settingList
->GetValue())
961 addonIDs
.push_back(std::static_pointer_cast
<CSettingAddon
>(addon
)->GetValue());
965 setting
= std::static_pointer_cast
<CSettingAddon
>(m_pSetting
);
966 addonIDs
.push_back(setting
->GetValue());
969 if (CGUIWindowAddonBrowser::SelectAddonID(
970 setting
->GetAddonType(), addonIDs
, setting
->AllowEmpty(),
971 buttonControl
->ShowAddonDetails(), m_pSetting
->GetType() == SettingType::List
,
972 buttonControl
->ShowInstalledAddons(), buttonControl
->ShowInstallableAddons(),
973 buttonControl
->ShowMoreAddons()) != 1)
976 if (m_pSetting
->GetType() == SettingType::List
)
977 std::static_pointer_cast
<CSettingList
>(m_pSetting
)->FromString(addonIDs
);
979 SetValid(setting
->SetValue(addonIDs
[0]));
981 else if (controlFormat
== "path" || controlFormat
== "file" || controlFormat
== "image")
982 SetValid(GetPath(std::static_pointer_cast
<CSettingPath
>(m_pSetting
), m_localizer
));
983 else if (controlFormat
== "date")
985 std::shared_ptr
<CSettingDate
> settingDate
=
986 std::static_pointer_cast
<CSettingDate
>(m_pSetting
);
988 KODI::TIME::SystemTime systemdate
;
989 settingDate
->GetDate().GetAsSystemTime(systemdate
);
990 if (CGUIDialogNumeric::ShowAndGetDate(systemdate
, Localize(buttonControl
->GetHeading())))
991 SetValid(settingDate
->SetDate(CDateTime(systemdate
)));
993 else if (controlFormat
== "time")
995 std::shared_ptr
<CSettingTime
> settingTime
=
996 std::static_pointer_cast
<CSettingTime
>(m_pSetting
);
998 KODI::TIME::SystemTime systemtime
;
999 settingTime
->GetTime().GetAsSystemTime(systemtime
);
1001 if (CGUIDialogNumeric::ShowAndGetTime(systemtime
, Localize(buttonControl
->GetHeading())))
1002 SetValid(settingTime
->SetTime(CDateTime(systemtime
)));
1004 else if (controlFormat
== "action")
1006 // simply call the OnSettingAction callback and whoever knows what to
1007 // do can do so (based on the setting's identification)
1008 m_pSetting
->OnSettingAction(m_pSetting
);
1012 else if (controlType
== "slider")
1014 float value
, min
, step
, max
;
1015 if (m_pSetting
->GetType() == SettingType::Integer
)
1017 std::shared_ptr
<CSettingInt
> settingInt
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1018 value
= (float)settingInt
->GetValue();
1019 min
= (float)settingInt
->GetMinimum();
1020 step
= (float)settingInt
->GetStep();
1021 max
= (float)settingInt
->GetMaximum();
1023 else if (m_pSetting
->GetType() == SettingType::Number
)
1025 std::shared_ptr
<CSettingNumber
> settingNumber
=
1026 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1027 value
= (float)settingNumber
->GetValue();
1028 min
= (float)settingNumber
->GetMinimum();
1029 step
= (float)settingNumber
->GetStep();
1030 max
= (float)settingNumber
->GetMaximum();
1035 std::shared_ptr
<const CSettingControlSlider
> sliderControl
=
1036 std::static_pointer_cast
<const CSettingControlSlider
>(control
);
1037 CGUIDialogSlider::ShowAndGetInput(Localize(sliderControl
->GetHeading()), value
, min
, step
, max
,
1042 // update the displayed value
1043 UpdateFromSetting(true);
1048 void CGUIControlButtonSetting::Update(bool fromControl
, bool updateDisplayOnly
)
1050 if (fromControl
|| m_pButton
== NULL
)
1053 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
1055 std::string strText
;
1056 std::shared_ptr
<const ISettingControl
> control
= m_pSetting
->GetControl();
1057 const std::string
& controlType
= control
->GetType();
1058 const std::string
& controlFormat
= control
->GetFormat();
1060 if (controlType
== "button")
1062 if (!std::static_pointer_cast
<const CSettingControlButton
>(control
)->HideValue())
1064 auto setting
= m_pSetting
;
1065 if (m_pSetting
->GetType() == SettingType::List
)
1066 setting
= std::static_pointer_cast
<CSettingList
>(m_pSetting
)->GetDefinition();
1068 switch (setting
->GetType())
1070 case SettingType::String
:
1072 if (controlFormat
== "addon")
1074 std::vector
<std::string
> addonIDs
;
1075 if (m_pSetting
->GetType() == SettingType::List
)
1077 for (const auto& addonSetting
:
1078 std::static_pointer_cast
<CSettingList
>(m_pSetting
)->GetValue())
1080 std::static_pointer_cast
<CSettingAddon
>(addonSetting
)->GetValue());
1083 addonIDs
.push_back(std::static_pointer_cast
<CSettingString
>(setting
)->GetValue());
1085 std::vector
<std::string
> addonNames
;
1086 for (const auto& addonID
: addonIDs
)
1088 ADDON::AddonPtr addon
;
1089 if (CServiceBroker::GetAddonMgr().GetAddon(addonID
, addon
,
1090 ADDON::OnlyEnabled::CHOICE_YES
))
1091 addonNames
.push_back(addon
->Name());
1094 if (addonNames
.empty())
1095 strText
= g_localizeStrings
.Get(231); // None
1097 strText
= StringUtils::Join(addonNames
, ", ");
1101 std::string strValue
= std::static_pointer_cast
<CSettingString
>(setting
)->GetValue();
1102 if (controlFormat
== "path" || controlFormat
== "file" || controlFormat
== "image")
1104 std::string shortPath
;
1105 if (CUtil::MakeShortenPath(strValue
, shortPath
, 30))
1106 strText
= shortPath
;
1108 else if (controlFormat
== "infolabel")
1111 if (strText
.empty())
1112 strText
= g_localizeStrings
.Get(231); // None
1121 case SettingType::Action
:
1124 // Note: This can be removed once all settings use a proper control & format combination.
1125 // CSettingAction is strictly speaking not designed to have a label2, it does not even have a value.
1126 strText
= m_pButton
->GetLabel2();
1136 else if (controlType
== "slider")
1138 switch (m_pSetting
->GetType())
1140 case SettingType::Integer
:
1142 std::shared_ptr
<const CSettingInt
> settingInt
=
1143 std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1144 strText
= CGUIControlSliderSetting::GetText(m_pSetting
, settingInt
->GetValue(),
1145 settingInt
->GetMinimum(), settingInt
->GetStep(),
1146 settingInt
->GetMaximum(), m_localizer
);
1150 case SettingType::Number
:
1152 std::shared_ptr
<const CSettingNumber
> settingNumber
=
1153 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1154 strText
= CGUIControlSliderSetting::GetText(
1155 m_pSetting
, settingNumber
->GetValue(), settingNumber
->GetMinimum(),
1156 settingNumber
->GetStep(), settingNumber
->GetMaximum(), m_localizer
);
1165 m_pButton
->SetLabel2(strText
);
1168 bool CGUIControlButtonSetting::GetPath(const std::shared_ptr
<CSettingPath
>& pathSetting
,
1169 ILocalizer
* localizer
)
1171 if (pathSetting
== NULL
)
1174 std::string path
= pathSetting
->GetValue();
1177 bool localSharesOnly
= false;
1178 const std::vector
<std::string
>& sources
= pathSetting
->GetSources();
1179 for (const auto& source
: sources
)
1181 if (StringUtils::EqualsNoCase(source
, "local"))
1182 localSharesOnly
= true;
1185 VECSOURCES
* sources
= CMediaSourceSettings::GetInstance().GetSources(source
);
1186 if (sources
!= NULL
)
1187 shares
.insert(shares
.end(), sources
->begin(), sources
->end());
1191 CServiceBroker::GetMediaManager().GetLocalDrives(shares
);
1192 if (!localSharesOnly
)
1193 CServiceBroker::GetMediaManager().GetNetworkLocations(shares
);
1195 bool result
= false;
1196 std::shared_ptr
<const CSettingControlButton
> control
=
1197 std::static_pointer_cast
<const CSettingControlButton
>(pathSetting
->GetControl());
1198 const auto heading
= ::Localize(control
->GetHeading(), localizer
);
1199 if (control
->GetFormat() == "file")
1200 result
= CGUIDialogFileBrowser::ShowAndGetFile(
1201 shares
, pathSetting
->GetMasking(CServiceBroker::GetFileExtensionProvider()), heading
, path
,
1202 control
->UseImageThumbs(), control
->UseFileDirectories());
1203 else if (control
->GetFormat() == "image")
1205 /* Check setting contains own masking, to filter required image type.
1206 * e.g. png only needed
1208 * <masking>*.png</masking>
1210 * <control type="button" format="image">
1213 std::string ext
= pathSetting
->GetMasking(CServiceBroker::GetFileExtensionProvider());
1215 ext
= CServiceBroker::GetFileExtensionProvider().GetPictureExtensions();
1216 result
= CGUIDialogFileBrowser::ShowAndGetFile(shares
, ext
, heading
, path
, true);
1220 CGUIDialogFileBrowser::ShowAndGetDirectory(shares
, heading
, path
, pathSetting
->Writable());
1225 return pathSetting
->SetValue(path
);
1228 void CGUIControlButtonSetting::OnSliderChange(void* data
, CGUISliderControl
* slider
)
1233 std::string strText
;
1234 switch (m_pSetting
->GetType())
1236 case SettingType::Integer
:
1238 std::shared_ptr
<CSettingInt
> settingInt
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1239 if (settingInt
->SetValue(slider
->GetIntValue()))
1240 strText
= CGUIControlSliderSetting::GetText(m_pSetting
, settingInt
->GetValue(),
1241 settingInt
->GetMinimum(), settingInt
->GetStep(),
1242 settingInt
->GetMaximum(), m_localizer
);
1246 case SettingType::Number
:
1248 std::shared_ptr
<CSettingNumber
> settingNumber
=
1249 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1250 if (settingNumber
->SetValue(static_cast<double>(slider
->GetFloatValue())))
1251 strText
= CGUIControlSliderSetting::GetText(
1252 m_pSetting
, settingNumber
->GetValue(), settingNumber
->GetMinimum(),
1253 settingNumber
->GetStep(), settingNumber
->GetMaximum(), m_localizer
);
1261 if (!strText
.empty())
1262 slider
->SetTextValue(strText
);
1265 CGUIControlEditSetting::CGUIControlEditSetting(CGUIEditControl
* pEdit
,
1267 const std::shared_ptr
<CSetting
>& pSetting
,
1268 ILocalizer
* localizer
)
1269 : CGUIControlBaseSetting(id
, pSetting
, localizer
)
1271 std::shared_ptr
<const CSettingControlEdit
> control
=
1272 std::static_pointer_cast
<const CSettingControlEdit
>(pSetting
->GetControl());
1274 if (m_pEdit
== NULL
)
1278 int heading
= m_pSetting
->GetLabel();
1279 if (control
->GetHeading() > 0)
1280 heading
= control
->GetHeading();
1284 CGUIEditControl::INPUT_TYPE inputType
= CGUIEditControl::INPUT_TYPE_TEXT
;
1285 const std::string
& controlFormat
= control
->GetFormat();
1286 if (controlFormat
== "string")
1288 if (control
->IsHidden())
1289 inputType
= CGUIEditControl::INPUT_TYPE_PASSWORD
;
1291 else if (controlFormat
== "integer" || controlFormat
== "number")
1293 if (control
->VerifyNewValue())
1294 inputType
= CGUIEditControl::INPUT_TYPE_PASSWORD_NUMBER_VERIFY_NEW
;
1296 inputType
= CGUIEditControl::INPUT_TYPE_NUMBER
;
1298 else if (controlFormat
== "ip")
1299 inputType
= CGUIEditControl::INPUT_TYPE_IPADDRESS
;
1300 else if (controlFormat
== "md5")
1301 inputType
= CGUIEditControl::INPUT_TYPE_PASSWORD_MD5
;
1303 m_pEdit
->SetInputType(inputType
, heading
);
1305 // this will automatically trigger validation so it must be executed after
1306 // having set the value of the control based on the value of the setting
1307 m_pEdit
->SetInputValidation(InputValidation
, this);
1310 CGUIControlEditSetting::~CGUIControlEditSetting() = default;
1312 bool CGUIControlEditSetting::OnClick()
1314 if (m_pEdit
== NULL
)
1317 // update our string
1318 if (m_pSetting
->GetControl()->GetFormat() == "urlencoded")
1320 std::shared_ptr
<CSettingUrlEncodedString
> urlEncodedSetting
=
1321 std::static_pointer_cast
<CSettingUrlEncodedString
>(m_pSetting
);
1322 SetValid(urlEncodedSetting
->SetDecodedValue(m_pEdit
->GetLabel2()));
1325 SetValid(m_pSetting
->FromString(m_pEdit
->GetLabel2()));
1330 void CGUIControlEditSetting::Update(bool fromControl
, bool updateDisplayOnly
)
1332 if (fromControl
|| m_pEdit
== NULL
)
1335 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
1337 std::shared_ptr
<const CSettingControlEdit
> control
=
1338 std::static_pointer_cast
<const CSettingControlEdit
>(m_pSetting
->GetControl());
1340 if (control
->GetFormat() == "urlencoded")
1342 std::shared_ptr
<CSettingUrlEncodedString
> urlEncodedSetting
=
1343 std::static_pointer_cast
<CSettingUrlEncodedString
>(m_pSetting
);
1344 m_pEdit
->SetLabel2(urlEncodedSetting
->GetDecodedValue());
1347 m_pEdit
->SetLabel2(m_pSetting
->ToString());
1350 bool CGUIControlEditSetting::InputValidation(const std::string
& input
, void* data
)
1355 CGUIControlEditSetting
* editControl
= reinterpret_cast<CGUIControlEditSetting
*>(data
);
1356 if (editControl
->GetSetting() == NULL
)
1359 editControl
->SetValid(editControl
->GetSetting()->CheckValidity(input
));
1360 return editControl
->IsValid();
1363 CGUIControlSliderSetting::CGUIControlSliderSetting(CGUISettingsSliderControl
* pSlider
,
1365 std::shared_ptr
<CSetting
> pSetting
,
1366 ILocalizer
* localizer
)
1367 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
1369 m_pSlider
= pSlider
;
1370 if (m_pSlider
== NULL
)
1373 m_pSlider
->SetID(id
);
1375 switch (m_pSetting
->GetType())
1377 case SettingType::Integer
:
1379 std::shared_ptr
<CSettingInt
> settingInt
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1380 if (m_pSetting
->GetControl()->GetFormat() == "percentage")
1381 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_PERCENTAGE
);
1384 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_INT
);
1385 m_pSlider
->SetRange(settingInt
->GetMinimum(), settingInt
->GetMaximum());
1387 m_pSlider
->SetIntInterval(settingInt
->GetStep());
1391 case SettingType::Number
:
1393 std::shared_ptr
<CSettingNumber
> settingNumber
=
1394 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1395 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_FLOAT
);
1396 m_pSlider
->SetFloatRange(static_cast<float>(settingNumber
->GetMinimum()),
1397 static_cast<float>(settingNumber
->GetMaximum()));
1398 m_pSlider
->SetFloatInterval(static_cast<float>(settingNumber
->GetStep()));
1407 CGUIControlSliderSetting::~CGUIControlSliderSetting() = default;
1409 bool CGUIControlSliderSetting::OnClick()
1411 if (m_pSlider
== NULL
)
1414 switch (m_pSetting
->GetType())
1416 case SettingType::Integer
:
1418 std::static_pointer_cast
<CSettingInt
>(m_pSetting
)->SetValue(m_pSlider
->GetIntValue()));
1421 case SettingType::Number
:
1422 SetValid(std::static_pointer_cast
<CSettingNumber
>(m_pSetting
)
1423 ->SetValue(static_cast<double>(m_pSlider
->GetFloatValue())));
1433 void CGUIControlSliderSetting::Update(bool fromControl
, bool updateDisplayOnly
)
1435 if (m_pSlider
== NULL
)
1438 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
1440 std::string strText
;
1441 switch (m_pSetting
->GetType())
1443 case SettingType::Integer
:
1445 std::shared_ptr
<const CSettingInt
> settingInt
=
1446 std::static_pointer_cast
<CSettingInt
>(m_pSetting
);
1449 value
= m_pSlider
->GetIntValue();
1452 value
= std::static_pointer_cast
<CSettingInt
>(m_pSetting
)->GetValue();
1453 m_pSlider
->SetIntValue(value
);
1456 strText
= CGUIControlSliderSetting::GetText(m_pSetting
, value
, settingInt
->GetMinimum(),
1457 settingInt
->GetStep(), settingInt
->GetMaximum(),
1462 case SettingType::Number
:
1464 std::shared_ptr
<const CSettingNumber
> settingNumber
=
1465 std::static_pointer_cast
<CSettingNumber
>(m_pSetting
);
1468 value
= static_cast<double>(m_pSlider
->GetFloatValue());
1471 value
= std::static_pointer_cast
<CSettingNumber
>(m_pSetting
)->GetValue();
1472 m_pSlider
->SetFloatValue((float)value
);
1475 strText
= CGUIControlSliderSetting::GetText(m_pSetting
, value
, settingNumber
->GetMinimum(),
1476 settingNumber
->GetStep(),
1477 settingNumber
->GetMaximum(), m_localizer
);
1485 if (!strText
.empty())
1486 m_pSlider
->SetTextValue(strText
);
1489 std::string
CGUIControlSliderSetting::GetText(const std::shared_ptr
<CSetting
>& setting
,
1490 const CVariant
& value
,
1491 const CVariant
& minimum
,
1492 const CVariant
& step
,
1493 const CVariant
& maximum
,
1494 ILocalizer
* localizer
)
1496 if (setting
== NULL
|| !(value
.isInteger() || value
.isDouble()))
1499 const auto control
= std::static_pointer_cast
<const CSettingControlSlider
>(setting
->GetControl());
1500 if (control
== NULL
)
1503 SettingControlSliderFormatter formatter
= control
->GetFormatter();
1504 if (formatter
!= NULL
)
1505 return formatter(control
, value
, minimum
, step
, maximum
);
1507 std::string formatString
= control
->GetFormatString();
1508 if (control
->GetFormatLabel() > -1)
1509 formatString
= ::Localize(control
->GetFormatLabel(), localizer
);
1511 std::string formattedString
;
1512 if (FormatText(formatString
, value
, setting
->GetId(), formattedString
))
1513 return formattedString
;
1515 // fall back to default formatting
1516 formatString
= control
->GetDefaultFormatString();
1517 if (FormatText(formatString
, value
, setting
->GetId(), formattedString
))
1518 return formattedString
;
1523 bool CGUIControlSliderSetting::FormatText(const std::string
& formatString
,
1524 const CVariant
& value
,
1525 const std::string
& settingId
,
1526 std::string
& formattedText
)
1530 if (value
.isDouble())
1531 formattedText
= StringUtils::Format(formatString
, value
.asDouble());
1533 formattedText
= StringUtils::Format(formatString
, static_cast<int>(value
.asInteger()));
1535 catch (const std::runtime_error
& err
)
1537 CLog::Log(LOGERROR
, "Invalid formatting with string \"{}\" for setting \"{}\": {}",
1538 formatString
, settingId
, err
.what());
1545 CGUIControlRangeSetting::CGUIControlRangeSetting(CGUISettingsSliderControl
* pSlider
,
1547 std::shared_ptr
<CSetting
> pSetting
,
1548 ILocalizer
* localizer
)
1549 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
1551 m_pSlider
= pSlider
;
1552 if (m_pSlider
== NULL
)
1555 m_pSlider
->SetID(id
);
1556 m_pSlider
->SetRangeSelection(true);
1558 if (m_pSetting
->GetType() == SettingType::List
)
1560 std::shared_ptr
<CSettingList
> settingList
= std::static_pointer_cast
<CSettingList
>(m_pSetting
);
1561 SettingConstPtr listDefintion
= settingList
->GetDefinition();
1562 switch (listDefintion
->GetType())
1564 case SettingType::Integer
:
1566 std::shared_ptr
<const CSettingInt
> listDefintionInt
=
1567 std::static_pointer_cast
<const CSettingInt
>(listDefintion
);
1568 if (m_pSetting
->GetControl()->GetFormat() == "percentage")
1569 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_PERCENTAGE
);
1572 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_INT
);
1573 m_pSlider
->SetRange(listDefintionInt
->GetMinimum(), listDefintionInt
->GetMaximum());
1575 m_pSlider
->SetIntInterval(listDefintionInt
->GetStep());
1579 case SettingType::Number
:
1581 std::shared_ptr
<const CSettingNumber
> listDefinitionNumber
=
1582 std::static_pointer_cast
<const CSettingNumber
>(listDefintion
);
1583 m_pSlider
->SetType(SLIDER_CONTROL_TYPE_FLOAT
);
1584 m_pSlider
->SetFloatRange(static_cast<float>(listDefinitionNumber
->GetMinimum()),
1585 static_cast<float>(listDefinitionNumber
->GetMaximum()));
1586 m_pSlider
->SetFloatInterval(static_cast<float>(listDefinitionNumber
->GetStep()));
1596 CGUIControlRangeSetting::~CGUIControlRangeSetting() = default;
1598 bool CGUIControlRangeSetting::OnClick()
1600 if (m_pSlider
== NULL
|| m_pSetting
->GetType() != SettingType::List
)
1603 std::shared_ptr
<CSettingList
> settingList
= std::static_pointer_cast
<CSettingList
>(m_pSetting
);
1604 const SettingList
& settingListValues
= settingList
->GetValue();
1605 if (settingListValues
.size() != 2)
1608 std::vector
<CVariant
> values
;
1609 SettingConstPtr listDefintion
= settingList
->GetDefinition();
1610 switch (listDefintion
->GetType())
1612 case SettingType::Integer
:
1613 values
.emplace_back(m_pSlider
->GetIntValue(CGUISliderControl::RangeSelectorLower
));
1614 values
.emplace_back(m_pSlider
->GetIntValue(CGUISliderControl::RangeSelectorUpper
));
1617 case SettingType::Number
:
1618 values
.emplace_back(m_pSlider
->GetFloatValue(CGUISliderControl::RangeSelectorLower
));
1619 values
.emplace_back(m_pSlider
->GetFloatValue(CGUISliderControl::RangeSelectorUpper
));
1626 if (values
.size() != 2)
1629 SetValid(CSettingUtils::SetList(settingList
, values
));
1633 void CGUIControlRangeSetting::Update(bool fromControl
, bool updateDisplayOnly
)
1635 if (m_pSlider
== NULL
|| m_pSetting
->GetType() != SettingType::List
)
1638 CGUIControlBaseSetting::Update(fromControl
, updateDisplayOnly
);
1640 std::shared_ptr
<CSettingList
> settingList
= std::static_pointer_cast
<CSettingList
>(m_pSetting
);
1641 const SettingList
& settingListValues
= settingList
->GetValue();
1642 if (settingListValues
.size() != 2)
1645 SettingConstPtr listDefintion
= settingList
->GetDefinition();
1646 std::shared_ptr
<const CSettingControlRange
> controlRange
=
1647 std::static_pointer_cast
<const CSettingControlRange
>(m_pSetting
->GetControl());
1648 const std::string
& controlFormat
= controlRange
->GetFormat();
1650 std::string strText
;
1651 std::string strTextLower
, strTextUpper
;
1652 std::string formatString
=
1653 Localize(controlRange
->GetFormatLabel() > -1 ? controlRange
->GetFormatLabel() : 21469);
1654 std::string valueFormat
= controlRange
->GetValueFormat();
1655 if (controlRange
->GetValueFormatLabel() > -1)
1656 valueFormat
= Localize(controlRange
->GetValueFormatLabel());
1658 switch (listDefintion
->GetType())
1660 case SettingType::Integer
:
1662 int valueLower
, valueUpper
;
1665 valueLower
= m_pSlider
->GetIntValue(CGUISliderControl::RangeSelectorLower
);
1666 valueUpper
= m_pSlider
->GetIntValue(CGUISliderControl::RangeSelectorUpper
);
1670 valueLower
= std::static_pointer_cast
<CSettingInt
>(settingListValues
[0])->GetValue();
1671 valueUpper
= std::static_pointer_cast
<CSettingInt
>(settingListValues
[1])->GetValue();
1672 m_pSlider
->SetIntValue(valueLower
, CGUISliderControl::RangeSelectorLower
);
1673 m_pSlider
->SetIntValue(valueUpper
, CGUISliderControl::RangeSelectorUpper
);
1676 if (controlFormat
== "date" || controlFormat
== "time")
1678 CDateTime
dateLower((time_t)valueLower
);
1679 CDateTime
dateUpper((time_t)valueUpper
);
1681 if (controlFormat
== "date")
1683 if (valueFormat
.empty())
1685 strTextLower
= dateLower
.GetAsLocalizedDate();
1686 strTextUpper
= dateUpper
.GetAsLocalizedDate();
1690 strTextLower
= dateLower
.GetAsLocalizedDate(valueFormat
);
1691 strTextUpper
= dateUpper
.GetAsLocalizedDate(valueFormat
);
1696 if (valueFormat
.empty())
1697 valueFormat
= "mm:ss";
1699 strTextLower
= dateLower
.GetAsLocalizedTime(valueFormat
);
1700 strTextUpper
= dateUpper
.GetAsLocalizedTime(valueFormat
);
1705 strTextLower
= StringUtils::Format(valueFormat
, valueLower
);
1706 strTextUpper
= StringUtils::Format(valueFormat
, valueUpper
);
1709 if (valueLower
!= valueUpper
)
1710 strText
= StringUtils::Format(formatString
, strTextLower
, strTextUpper
);
1712 strText
= strTextLower
;
1716 case SettingType::Number
:
1718 double valueLower
, valueUpper
;
1722 static_cast<double>(m_pSlider
->GetFloatValue(CGUISliderControl::RangeSelectorLower
));
1724 static_cast<double>(m_pSlider
->GetFloatValue(CGUISliderControl::RangeSelectorUpper
));
1728 valueLower
= std::static_pointer_cast
<CSettingNumber
>(settingListValues
[0])->GetValue();
1729 valueUpper
= std::static_pointer_cast
<CSettingNumber
>(settingListValues
[1])->GetValue();
1730 m_pSlider
->SetFloatValue((float)valueLower
, CGUISliderControl::RangeSelectorLower
);
1731 m_pSlider
->SetFloatValue((float)valueUpper
, CGUISliderControl::RangeSelectorUpper
);
1734 strTextLower
= StringUtils::Format(valueFormat
, valueLower
);
1735 if (valueLower
!= valueUpper
)
1737 strTextUpper
= StringUtils::Format(valueFormat
, valueUpper
);
1738 strText
= StringUtils::Format(formatString
, strTextLower
, strTextUpper
);
1741 strText
= strTextLower
;
1750 if (!strText
.empty())
1751 m_pSlider
->SetTextValue(strText
);
1754 CGUIControlSeparatorSetting::CGUIControlSeparatorSetting(CGUIImage
* pImage
,
1756 ILocalizer
* localizer
)
1757 : CGUIControlBaseSetting(id
, NULL
, localizer
)
1760 if (m_pImage
== NULL
)
1763 m_pImage
->SetID(id
);
1766 CGUIControlSeparatorSetting::~CGUIControlSeparatorSetting() = default;
1768 CGUIControlGroupTitleSetting::CGUIControlGroupTitleSetting(CGUILabelControl
* pLabel
,
1770 ILocalizer
* localizer
)
1771 : CGUIControlBaseSetting(id
, NULL
, localizer
)
1774 if (m_pLabel
== NULL
)
1777 m_pLabel
->SetID(id
);
1780 CGUIControlGroupTitleSetting::~CGUIControlGroupTitleSetting() = default;
1782 CGUIControlLabelSetting::CGUIControlLabelSetting(CGUIButtonControl
* pButton
,
1784 std::shared_ptr
<CSetting
> pSetting
,
1785 ILocalizer
* localizer
)
1786 : CGUIControlBaseSetting(id
, std::move(pSetting
), localizer
)
1788 m_pButton
= pButton
;
1789 if (m_pButton
== NULL
)
1792 m_pButton
->SetID(id
);
1793 UpdateFromSetting();