2 * Copyright (C) 2014-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 "GUIDialogSettingsBase.h"
11 #include "GUIUserMessages.h"
12 #include "ServiceBroker.h"
13 #include "dialogs/GUIDialogYesNo.h"
14 #include "guilib/GUIColorButtonControl.h"
15 #include "guilib/GUIComponent.h"
16 #include "guilib/GUIControlGroupList.h"
17 #include "guilib/GUIEditControl.h"
18 #include "guilib/GUIImage.h"
19 #include "guilib/GUILabelControl.h"
20 #include "guilib/GUIRadioButtonControl.h"
21 #include "guilib/GUISettingsSliderControl.h"
22 #include "guilib/GUISpinControlEx.h"
23 #include "guilib/GUIToggleButtonControl.h"
24 #include "guilib/GUIWindowManager.h"
25 #include "guilib/LocalizeStrings.h"
26 #include "input/actions/Action.h"
27 #include "input/actions/ActionIDs.h"
28 #include "settings/SettingControl.h"
29 #include "settings/lib/SettingSection.h"
30 #include "settings/windows/GUIControlSettings.h"
31 #include "utils/StringUtils.h"
32 #include "utils/Variant.h"
39 #if defined(TARGET_WINDOWS) // disable 4355: 'this' used in base member initializer list
41 #pragma warning(disable : 4355)
42 #endif // defined(TARGET_WINDOWS)
44 #define CATEGORY_GROUP_ID 3
45 #define SETTINGS_GROUP_ID 5
47 #define CONTROL_DEFAULT_BUTTON 7
48 #define CONTROL_DEFAULT_RADIOBUTTON 8
49 #define CONTROL_DEFAULT_SPIN 9
50 #define CONTROL_DEFAULT_CATEGORY_BUTTON 10
51 #define CONTROL_DEFAULT_SEPARATOR 11
52 #define CONTROL_DEFAULT_EDIT 12
53 #define CONTROL_DEFAULT_SLIDER 13
54 #define CONTROL_DEFAULT_SETTING_LABEL 14
55 #define CONTROL_DEFAULT_COLORBUTTON 15
57 CGUIDialogSettingsBase::CGUIDialogSettingsBase(int windowId
, const std::string
& xmlFile
)
58 : CGUIDialog(windowId
, xmlFile
),
60 m_dummyCategory(NULL
),
61 m_pOriginalSpin(NULL
),
62 m_pOriginalSlider(NULL
),
63 m_pOriginalRadioButton(NULL
),
64 m_pOriginalCategoryButton(NULL
),
65 m_pOriginalButton(NULL
),
66 m_pOriginalEdit(NULL
),
67 m_pOriginalImage(NULL
),
68 m_pOriginalGroupTitle(NULL
),
71 m_loadType
= KEEP_IN_MEMORY
;
74 CGUIDialogSettingsBase::~CGUIDialogSettingsBase()
80 bool CGUIDialogSettingsBase::OnMessage(CGUIMessage
& message
)
82 switch (message
.GetMessage())
84 case GUI_MSG_WINDOW_INIT
:
86 m_delayedSetting
.reset();
87 if (message
.GetParam1() != WINDOW_INVALID
)
88 { // coming to this window first time (ie not returning back from some other window)
89 // so we reset our section and control states
94 if (AllowResettingSettings())
96 m_resetSetting
= std::make_shared
<CSettingAction
>(SETTINGS_RESET_SETTING_ID
);
97 m_resetSetting
->SetLabel(10041);
98 m_resetSetting
->SetHelp(10045);
99 m_resetSetting
->SetControl(CreateControl("button"));
102 m_dummyCategory
= std::make_shared
<CSettingCategory
>(SETTINGS_EMPTY_CATEGORY_ID
);
103 m_dummyCategory
->SetLabel(10046);
104 m_dummyCategory
->SetHelp(10047);
108 case GUI_MSG_WINDOW_DEINIT
:
110 // cancel any delayed changes
111 if (m_delayedSetting
!= NULL
)
113 m_delayedTimer
.Stop();
114 CGUIMessage
message(GUI_MSG_UPDATE_ITEM
, GetID(), m_delayedSetting
->GetID());
118 CGUIDialog::OnMessage(message
);
123 case GUI_MSG_FOCUSED
:
125 CGUIDialog::OnMessage(message
);
126 m_focusedControl
= GetFocusedControlID();
128 // cancel any delayed changes
129 if (m_delayedSetting
!= NULL
&& m_delayedSetting
->GetID() != m_focusedControl
)
131 m_delayedTimer
.Stop();
132 // param1 = 1 for "reset the control if it's invalid"
133 CGUIMessage
message(GUI_MSG_UPDATE_ITEM
, GetID(), m_delayedSetting
->GetID(), 1);
134 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message
, GetID());
136 // update the value of the previous setting (in case it was invalid)
137 else if (m_iSetting
>= CONTROL_SETTINGS_START_CONTROL
&&
138 m_iSetting
< (int)(CONTROL_SETTINGS_START_CONTROL
+ m_settingControls
.size()))
140 BaseSettingControlPtr control
= GetSettingControl(m_iSetting
);
141 if (control
!= NULL
&& control
->GetSetting() != NULL
&& !control
->IsValid())
143 // param1 = 1 for "reset the control if it's invalid"
144 // param2 = 1 for "only update the current value"
145 CGUIMessage
message(GUI_MSG_UPDATE_ITEM
, GetID(), m_iSetting
, 1, 1);
146 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message
, GetID());
150 CVariant description
;
152 // check if we have changed the category and need to create new setting controls
153 if (m_focusedControl
>= CONTROL_SETTINGS_START_BUTTONS
&&
154 m_focusedControl
< (int)(CONTROL_SETTINGS_START_BUTTONS
+ m_categories
.size()))
156 int categoryIndex
= m_focusedControl
- CONTROL_SETTINGS_START_BUTTONS
;
157 SettingCategoryPtr category
= m_categories
.at(categoryIndex
);
158 if (categoryIndex
!= m_iCategory
)
160 if (!category
->CanAccess())
162 // unable to go to this category - focus the previous one
163 SET_CONTROL_FOCUS(CONTROL_SETTINGS_START_BUTTONS
+ m_iCategory
, 0);
167 m_iCategory
= categoryIndex
;
171 description
= category
->GetHelp();
173 else if (m_focusedControl
>= CONTROL_SETTINGS_START_CONTROL
&&
174 m_focusedControl
< (int)(CONTROL_SETTINGS_START_CONTROL
+ m_settingControls
.size()))
176 m_iSetting
= m_focusedControl
;
177 std::shared_ptr
<CSetting
> setting
= GetSettingControl(m_focusedControl
)->GetSetting();
179 description
= setting
->GetHelp();
182 // set the description of the currently focused category/setting
183 if (description
.isInteger() || (description
.isString() && !description
.empty()))
184 SetDescription(description
);
189 case GUI_MSG_CLICKED
:
191 int iControl
= message
.GetSenderId();
192 if (iControl
== CONTROL_SETTINGS_OKAY_BUTTON
)
203 if (iControl
== CONTROL_SETTINGS_CANCEL_BUTTON
)
210 BaseSettingControlPtr control
= GetSettingControl(iControl
);
217 case GUI_MSG_UPDATE_ITEM
:
219 if (m_delayedSetting
!= NULL
&& m_delayedSetting
->GetID() == message
.GetControlId())
221 // first get the delayed setting and reset its member variable
222 // to avoid handling the delayed setting twice in case the OnClick()
223 // performed later causes the window to be deinitialized (e.g. when
224 // changing the language)
225 BaseSettingControlPtr delayedSetting
= m_delayedSetting
;
226 m_delayedSetting
.reset();
228 // if updating the setting fails and param1 has been specifically set
229 // we need to call OnSettingChanged() to restore a valid value in the
231 if (!delayedSetting
->OnClick() && message
.GetParam1() != 0)
232 OnSettingChanged(delayedSetting
->GetSetting());
236 if (message
.GetControlId() >= CONTROL_SETTINGS_START_CONTROL
&&
237 message
.GetControlId() < (int)(CONTROL_SETTINGS_START_CONTROL
+ m_settingControls
.size()))
239 BaseSettingControlPtr settingControl
= GetSettingControl(message
.GetControlId());
240 if (settingControl
.get() != NULL
&& settingControl
->GetSetting() != NULL
)
242 settingControl
->UpdateFromSetting(message
.GetParam2() != 0);
251 if (IsActive() && HasID(message
.GetSenderId()))
253 int focusedControl
= GetFocusedControlID();
255 SET_CONTROL_FOCUS(focusedControl
, 0);
264 return CGUIDialog::OnMessage(message
);
267 bool CGUIDialogSettingsBase::OnAction(const CAction
& action
)
269 switch (action
.GetID())
271 case ACTION_SETTINGS_RESET
:
277 case ACTION_DELETE_ITEM
:
279 if (m_iSetting
>= CONTROL_SETTINGS_START_CONTROL
&&
280 m_iSetting
< (int)(CONTROL_SETTINGS_START_CONTROL
+ m_settingControls
.size()))
282 auto settingControl
= GetSettingControl(m_iSetting
);
283 if (settingControl
!= nullptr)
285 std::shared_ptr
<CSetting
> setting
= settingControl
->GetSetting();
286 if (setting
!= nullptr)
300 return CGUIDialog::OnAction(action
);
303 bool CGUIDialogSettingsBase::OnBack(int actionID
)
305 m_lastControlID
= 0; // don't save the control as we go to a different window each time
307 // if the setting dialog is not a window but a dialog we need to close differently
309 return CGUIWindow::OnBack(actionID
);
311 return CGUIDialog::OnBack(actionID
);
314 void CGUIDialogSettingsBase::DoProcess(unsigned int currentTime
, CDirtyRegionList
& dirtyregions
)
316 // update alpha status of current button
317 CGUIControl
* control
= GetFirstFocusableControl(CONTROL_SETTINGS_START_BUTTONS
+ m_iCategory
);
320 if (m_fadedControl
&&
321 (m_fadedControl
!= control
->GetID() || m_fadedControl
== m_focusedControl
))
323 if (control
->GetControlType() == CGUIControl::GUICONTROL_BUTTON
)
324 static_cast<CGUIButtonControl
*>(control
)->SetAlpha(0xFF);
326 static_cast<CGUIButtonControl
*>(control
)->SetSelected(false);
330 if (!control
->HasFocus())
332 m_fadedControl
= control
->GetID();
333 if (control
->GetControlType() == CGUIControl::GUICONTROL_BUTTON
)
334 static_cast<CGUIButtonControl
*>(control
)->SetAlpha(0x80);
335 else if (control
->GetControlType() == CGUIControl::GUICONTROL_TOGGLEBUTTON
)
336 static_cast<CGUIButtonControl
*>(control
)->SetSelected(true);
341 control
->SetFocus(true);
344 CGUIDialog::DoProcess(currentTime
, dirtyregions
);
347 void CGUIDialogSettingsBase::OnInitWindow()
351 CGUIDialog::OnInitWindow();
354 void CGUIDialogSettingsBase::SetupControls(bool createSettings
/* = true */)
356 // cleanup first, if necessary
360 m_pOriginalSpin
= dynamic_cast<CGUISpinControlEx
*>(GetControl(CONTROL_DEFAULT_SPIN
));
361 m_pOriginalSlider
= dynamic_cast<CGUISettingsSliderControl
*>(GetControl(CONTROL_DEFAULT_SLIDER
));
362 m_pOriginalRadioButton
=
363 dynamic_cast<CGUIRadioButtonControl
*>(GetControl(CONTROL_DEFAULT_RADIOBUTTON
));
364 m_pOriginalCategoryButton
=
365 dynamic_cast<CGUIButtonControl
*>(GetControl(CONTROL_DEFAULT_CATEGORY_BUTTON
));
366 m_pOriginalButton
= dynamic_cast<CGUIButtonControl
*>(GetControl(CONTROL_DEFAULT_BUTTON
));
367 m_pOriginalImage
= dynamic_cast<CGUIImage
*>(GetControl(CONTROL_DEFAULT_SEPARATOR
));
368 m_pOriginalEdit
= dynamic_cast<CGUIEditControl
*>(GetControl(CONTROL_DEFAULT_EDIT
));
369 m_pOriginalGroupTitle
=
370 dynamic_cast<CGUILabelControl
*>(GetControl(CONTROL_DEFAULT_SETTING_LABEL
));
371 m_pOriginalColorButton
=
372 dynamic_cast<CGUIColorButtonControl
*>(GetControl(CONTROL_DEFAULT_COLORBUTTON
));
374 // if there's no edit control but there's a button control use that instead
375 if (m_pOriginalEdit
== nullptr && m_pOriginalButton
!= nullptr)
377 m_pOriginalEdit
= new CGUIEditControl(*m_pOriginalButton
);
378 m_newOriginalEdit
= true;
381 // hide all default controls by default
382 if (m_pOriginalSpin
!= nullptr)
383 m_pOriginalSpin
->SetVisible(false);
384 if (m_pOriginalSlider
!= nullptr)
385 m_pOriginalSlider
->SetVisible(false);
386 if (m_pOriginalRadioButton
!= nullptr)
387 m_pOriginalRadioButton
->SetVisible(false);
388 if (m_pOriginalButton
!= nullptr)
389 m_pOriginalButton
->SetVisible(false);
390 if (m_pOriginalCategoryButton
!= nullptr)
391 m_pOriginalCategoryButton
->SetVisible(false);
392 if (m_pOriginalEdit
!= nullptr)
393 m_pOriginalEdit
->SetVisible(false);
394 if (m_pOriginalImage
!= nullptr)
395 m_pOriginalImage
->SetVisible(false);
396 if (m_pOriginalGroupTitle
!= nullptr)
397 m_pOriginalGroupTitle
->SetVisible(false);
398 if (m_pOriginalColorButton
!= nullptr)
399 m_pOriginalColorButton
->SetVisible(false);
402 SettingSectionPtr section
= GetSection();
406 // update the screen string
407 if (section
->GetLabel() >= 0)
408 SetHeading(section
->GetLabel());
410 // get the categories we need
411 m_categories
= section
->GetCategories((SettingLevel
)GetSettingLevel());
412 if (m_categories
.empty())
413 m_categories
.push_back(m_dummyCategory
);
415 if (m_pOriginalCategoryButton
!= NULL
)
417 // setup our control groups...
418 CGUIControlGroupList
* group
=
419 dynamic_cast<CGUIControlGroupList
*>(GetControl(CATEGORY_GROUP_ID
));
423 // go through the categories and create the necessary buttons
424 int buttonIdOffset
= 0;
425 for (SettingCategoryList::const_iterator category
= m_categories
.begin();
426 category
!= m_categories
.end(); ++category
)
428 CGUIButtonControl
* pButton
= NULL
;
429 if (m_pOriginalCategoryButton
->GetControlType() == CGUIControl::GUICONTROL_TOGGLEBUTTON
)
430 pButton
= new CGUIToggleButtonControl(
431 *static_cast<CGUIToggleButtonControl
*>(m_pOriginalCategoryButton
));
432 else if (m_pOriginalCategoryButton
->GetControlType() == CGUIControl::GUICONTROL_COLORBUTTON
)
433 pButton
= new CGUIColorButtonControl(
434 *static_cast<CGUIColorButtonControl
*>(m_pOriginalCategoryButton
));
436 pButton
= new CGUIButtonControl(*m_pOriginalCategoryButton
);
437 pButton
->SetLabel(GetSettingsLabel(*category
));
438 pButton
->SetID(CONTROL_SETTINGS_START_BUTTONS
+ buttonIdOffset
);
439 pButton
->SetVisible(true);
440 pButton
->AllocResources();
442 group
->AddControl(pButton
);
450 // set focus correctly depending on whether there are categories visible or not
451 if (m_pOriginalCategoryButton
== NULL
&&
452 (m_defaultControl
<= 0 || m_defaultControl
== CATEGORY_GROUP_ID
))
453 m_defaultControl
= SETTINGS_GROUP_ID
;
454 else if (m_pOriginalCategoryButton
!= NULL
&& m_defaultControl
<= 0)
455 m_defaultControl
= CATEGORY_GROUP_ID
;
458 void CGUIDialogSettingsBase::FreeControls()
460 // clear the category group
461 CGUIControlGroupList
* control
=
462 dynamic_cast<CGUIControlGroupList
*>(GetControl(CATEGORY_GROUP_ID
));
465 control
->FreeResources();
468 m_categories
.clear();
470 // If we created our own edit control instead of borrowing it then clean it up
471 if (m_newOriginalEdit
)
473 delete m_pOriginalEdit
;
474 m_pOriginalEdit
= nullptr;
475 m_newOriginalEdit
= false;
478 FreeSettingsControls();
481 void CGUIDialogSettingsBase::DeleteControls()
483 m_resetSetting
.reset();
484 m_dummyCategory
.reset();
487 void CGUIDialogSettingsBase::FreeSettingsControls()
489 // clear the settings group
490 CGUIControlGroupList
* control
=
491 dynamic_cast<CGUIControlGroupList
*>(GetControl(SETTINGS_GROUP_ID
));
494 control
->FreeResources();
498 for (std::vector
<BaseSettingControlPtr
>::iterator control
= m_settingControls
.begin();
499 control
!= m_settingControls
.end(); ++control
)
502 m_settingControls
.clear();
505 void CGUIDialogSettingsBase::OnTimeout()
507 UpdateSettingControl(m_delayedSetting
, true);
510 void CGUIDialogSettingsBase::OnSettingChanged(const std::shared_ptr
<const CSetting
>& setting
)
512 if (setting
== NULL
|| setting
->GetType() == SettingType::Unknown
||
513 setting
->GetType() == SettingType::Action
)
516 UpdateSettingControl(setting
->GetId(), true);
519 void CGUIDialogSettingsBase::OnSettingPropertyChanged(
520 const std::shared_ptr
<const CSetting
>& setting
, const char* propertyName
)
522 if (setting
== NULL
|| propertyName
== NULL
)
525 UpdateSettingControl(setting
->GetId());
528 std::string
CGUIDialogSettingsBase::GetLocalizedString(uint32_t labelId
) const
530 return g_localizeStrings
.Get(labelId
);
533 void CGUIDialogSettingsBase::SetupView()
538 std::set
<std::string
> CGUIDialogSettingsBase::CreateSettings()
540 FreeSettingsControls();
542 std::set
<std::string
> settingMap
;
544 if (m_categories
.size() <= 0)
547 if (m_iCategory
< 0 || m_iCategory
>= (int)m_categories
.size())
550 CGUIControlGroupList
* group
= dynamic_cast<CGUIControlGroupList
*>(GetControl(SETTINGS_GROUP_ID
));
554 SettingCategoryPtr category
= m_categories
.at(m_iCategory
);
555 if (category
== NULL
)
558 // set the description of the current category
559 SetDescription(category
->GetHelp());
561 const SettingGroupList
& groups
= category
->GetGroups((SettingLevel
)GetSettingLevel());
562 int iControlID
= CONTROL_SETTINGS_START_CONTROL
;
564 for (SettingGroupList::const_iterator groupIt
= groups
.begin(); groupIt
!= groups
.end();
567 if (*groupIt
== NULL
)
570 const SettingList
& settings
= (*groupIt
)->GetSettings((SettingLevel
)GetSettingLevel());
571 if (settings
.size() <= 0)
574 std::shared_ptr
<const CSettingControlTitle
> title
=
575 std::dynamic_pointer_cast
<const CSettingControlTitle
>((*groupIt
)->GetControl());
576 bool hideSeparator
= title
? title
->IsSeparatorHidden() : false;
577 bool separatorBelowGroupLabel
= title
? title
->IsSeparatorBelowLabel() : false;
578 int groupLabel
= (*groupIt
)->GetLabel();
580 // hide the separator for the first settings grouplist if it
581 // is the very first item in the list (also above the label)
586 hideSeparator
= true;
588 else if (!separatorBelowGroupLabel
&& !hideSeparator
)
589 AddSeparator(group
->GetWidth(), iControlID
);
592 AddGroupLabel(*groupIt
, group
->GetWidth(), iControlID
);
594 if (separatorBelowGroupLabel
&& !hideSeparator
)
595 AddSeparator(group
->GetWidth(), iControlID
);
597 for (SettingList::const_iterator settingIt
= settings
.begin(); settingIt
!= settings
.end();
600 const std::shared_ptr
<CSetting
>& pSetting
= *settingIt
;
601 settingMap
.insert(pSetting
->GetId());
602 AddSetting(pSetting
, group
->GetWidth(), iControlID
);
606 if (AllowResettingSettings() && !settingMap
.empty())
608 // add "Reset" control
609 AddSeparator(group
->GetWidth(), iControlID
);
610 AddSetting(m_resetSetting
, group
->GetWidth(), iControlID
);
613 // update our settings (turns controls on/off as appropriate)
621 std::string
CGUIDialogSettingsBase::GetSettingsLabel(const std::shared_ptr
<ISetting
>& pSetting
)
623 return GetLocalizedString(pSetting
->GetLabel());
626 void CGUIDialogSettingsBase::UpdateSettings()
628 for (std::vector
<BaseSettingControlPtr
>::iterator it
= m_settingControls
.begin();
629 it
!= m_settingControls
.end(); ++it
)
631 BaseSettingControlPtr pSettingControl
= *it
;
632 std::shared_ptr
<CSetting
> pSetting
= pSettingControl
->GetSetting();
633 CGUIControl
* pControl
= pSettingControl
->GetControl();
634 if (pSetting
== NULL
|| pControl
== NULL
)
637 pSettingControl
->UpdateFromSetting();
641 CGUIControl
* CGUIDialogSettingsBase::AddSetting(const std::shared_ptr
<CSetting
>& pSetting
,
645 if (pSetting
== NULL
)
648 BaseSettingControlPtr pSettingControl
;
649 CGUIControl
* pControl
= NULL
;
651 // determine the label and any possible indentation in case of sub settings
652 std::string label
= GetSettingsLabel(pSetting
);
653 int parentLevels
= 0;
654 std::shared_ptr
<CSetting
> parentSetting
= GetSetting(pSetting
->GetParent());
655 while (parentSetting
!= NULL
)
658 parentSetting
= GetSetting(parentSetting
->GetParent());
661 if (parentLevels
> 0)
663 // add additional 2 spaces indentation for anything past one level
664 std::string indentation
;
665 for (int index
= 1; index
< parentLevels
; index
++)
666 indentation
.append(" ");
667 label
= StringUtils::Format(g_localizeStrings
.Get(168), indentation
, label
);
670 // create the proper controls
671 if (!pSetting
->GetControl())
674 std::string controlType
= pSetting
->GetControl()->GetType();
675 if (controlType
== "toggle")
677 if (m_pOriginalRadioButton
!= NULL
)
678 pControl
= m_pOriginalRadioButton
->Clone();
679 if (pControl
== NULL
)
682 static_cast<CGUIRadioButtonControl
*>(pControl
)->SetLabel(label
);
683 pSettingControl
= std::make_shared
<CGUIControlRadioButtonSetting
>(
684 static_cast<CGUIRadioButtonControl
*>(pControl
), iControlID
, pSetting
, this);
686 else if (controlType
== "spinner")
688 if (m_pOriginalSpin
!= NULL
)
689 pControl
= new CGUISpinControlEx(*m_pOriginalSpin
);
690 if (pControl
== NULL
)
693 static_cast<CGUISpinControlEx
*>(pControl
)->SetText(label
);
694 pSettingControl
= std::make_shared
<CGUIControlSpinExSetting
>(
695 static_cast<CGUISpinControlEx
*>(pControl
), iControlID
, pSetting
, this);
697 else if (controlType
== "edit")
699 if (m_pOriginalEdit
!= NULL
)
700 pControl
= new CGUIEditControl(*m_pOriginalEdit
);
701 if (pControl
== NULL
)
704 static_cast<CGUIEditControl
*>(pControl
)->SetLabel(label
);
705 pSettingControl
= std::make_shared
<CGUIControlEditSetting
>(
706 static_cast<CGUIEditControl
*>(pControl
), iControlID
, pSetting
, this);
708 else if (controlType
== "list")
710 if (m_pOriginalButton
!= NULL
)
711 pControl
= new CGUIButtonControl(*m_pOriginalButton
);
712 if (pControl
== NULL
)
715 static_cast<CGUIButtonControl
*>(pControl
)->SetLabel(label
);
716 pSettingControl
= std::make_shared
<CGUIControlListSetting
>(
717 static_cast<CGUIButtonControl
*>(pControl
), iControlID
, pSetting
, this);
719 else if (controlType
== "button" || controlType
== "slider")
721 if (controlType
== "button" ||
722 std::static_pointer_cast
<const CSettingControlSlider
>(pSetting
->GetControl())->UsePopup())
724 if (m_pOriginalButton
!= NULL
)
725 pControl
= new CGUIButtonControl(*m_pOriginalButton
);
726 if (pControl
== NULL
)
729 static_cast<CGUIButtonControl
*>(pControl
)->SetLabel(label
);
730 pSettingControl
= std::make_shared
<CGUIControlButtonSetting
>(
731 static_cast<CGUIButtonControl
*>(pControl
), iControlID
, pSetting
, this);
735 if (m_pOriginalSlider
!= NULL
)
736 pControl
= m_pOriginalSlider
->Clone();
737 if (pControl
== NULL
)
740 static_cast<CGUISettingsSliderControl
*>(pControl
)->SetText(label
);
741 pSettingControl
= std::make_shared
<CGUIControlSliderSetting
>(
742 static_cast<CGUISettingsSliderControl
*>(pControl
), iControlID
, pSetting
, this);
745 else if (controlType
== "range")
747 if (m_pOriginalSlider
!= NULL
)
748 pControl
= m_pOriginalSlider
->Clone();
749 if (pControl
== NULL
)
752 static_cast<CGUISettingsSliderControl
*>(pControl
)->SetText(label
);
753 pSettingControl
= std::make_shared
<CGUIControlRangeSetting
>(
754 static_cast<CGUISettingsSliderControl
*>(pControl
), iControlID
, pSetting
, this);
756 else if (controlType
== "label")
758 if (m_pOriginalButton
!= NULL
)
759 pControl
= new CGUIButtonControl(*m_pOriginalButton
);
760 if (pControl
== NULL
)
763 static_cast<CGUIButtonControl
*>(pControl
)->SetLabel(label
);
764 pSettingControl
= std::make_shared
<CGUIControlLabelSetting
>(
765 static_cast<CGUIButtonControl
*>(pControl
), iControlID
, pSetting
, this);
767 else if (controlType
== "colorbutton")
769 if (m_pOriginalColorButton
)
770 pControl
= m_pOriginalColorButton
->Clone();
771 if (pControl
== nullptr)
774 static_cast<CGUIColorButtonControl
*>(pControl
)->SetLabel(label
);
775 pSettingControl
= std::make_shared
<CGUIControlColorButtonSetting
>(
776 static_cast<CGUIColorButtonControl
*>(pControl
), iControlID
, pSetting
, this);
781 if (pSetting
->GetControl()->GetDelayed())
782 pSettingControl
->SetDelayed();
784 return AddSettingControl(pControl
, pSettingControl
, width
, iControlID
);
787 CGUIControl
* CGUIDialogSettingsBase::AddSeparator(float width
, int& iControlID
)
789 if (m_pOriginalImage
== NULL
)
792 CGUIControl
* pControl
= new CGUIImage(*m_pOriginalImage
);
793 if (pControl
== NULL
)
796 return AddSettingControl(pControl
,
797 BaseSettingControlPtr(new CGUIControlSeparatorSetting(
798 static_cast<CGUIImage
*>(pControl
), iControlID
, this)),
802 CGUIControl
* CGUIDialogSettingsBase::AddGroupLabel(const std::shared_ptr
<CSettingGroup
>& group
,
806 if (m_pOriginalGroupTitle
== NULL
)
809 CGUIControl
* pControl
= new CGUILabelControl(*m_pOriginalGroupTitle
);
810 if (pControl
== NULL
)
813 static_cast<CGUILabelControl
*>(pControl
)->SetLabel(GetSettingsLabel(group
));
815 return AddSettingControl(pControl
,
816 BaseSettingControlPtr(new CGUIControlGroupTitleSetting(
817 static_cast<CGUILabelControl
*>(pControl
), iControlID
, this)),
821 CGUIControl
* CGUIDialogSettingsBase::AddSettingControl(CGUIControl
* pControl
,
822 BaseSettingControlPtr pSettingControl
,
826 if (pControl
== NULL
)
828 pSettingControl
.reset();
832 pControl
->SetID(iControlID
++);
833 pControl
->SetVisible(true);
834 pControl
->SetWidth(width
);
836 CGUIControlGroupList
* group
= dynamic_cast<CGUIControlGroupList
*>(GetControl(SETTINGS_GROUP_ID
));
839 pControl
->AllocResources();
840 group
->AddControl(pControl
);
842 m_settingControls
.push_back(pSettingControl
);
847 void CGUIDialogSettingsBase::SetHeading(const CVariant
& label
)
849 SetControlLabel(CONTROL_SETTINGS_LABEL
, label
);
852 void CGUIDialogSettingsBase::SetDescription(const CVariant
& label
)
854 SetControlLabel(CONTROL_SETTINGS_DESCRIPTION
, label
);
857 void CGUIDialogSettingsBase::OnResetSettings()
859 if (CGUIDialogYesNo::ShowAndGetInput(CVariant
{10041}, CVariant
{10042}))
861 for (std::vector
<BaseSettingControlPtr
>::iterator it
= m_settingControls
.begin();
862 it
!= m_settingControls
.end(); ++it
)
864 std::shared_ptr
<CSetting
> setting
= (*it
)->GetSetting();
871 void CGUIDialogSettingsBase::OnClick(const BaseSettingControlPtr
& pSettingControl
)
873 if (AllowResettingSettings() &&
874 pSettingControl
->GetSetting()->GetId() == SETTINGS_RESET_SETTING_ID
)
876 OnAction(CAction(ACTION_SETTINGS_RESET
));
880 // we need to first set the delayed setting and then execute OnClick()
881 // because OnClick() triggers OnSettingChanged() and there we need to
882 // know if the changed setting is delayed or not
883 if (pSettingControl
->IsDelayed())
885 m_delayedSetting
= pSettingControl
;
886 // for some controls we need to update its displayed data/text before
887 // OnClick() is called after the delay timer has expired because
888 // otherwise the displayed value of the control does not match with
889 // the user's interaction
890 pSettingControl
->UpdateFromControl();
892 // either start or restart the delay timer which will result in a call to
893 // the control's OnClick() method to update the setting's value
894 if (m_delayedTimer
.IsRunning())
895 m_delayedTimer
.Restart();
897 m_delayedTimer
.Start(GetDelayMs());
902 // if changing the setting fails
903 // we need to restore the proper state
904 if (!pSettingControl
->OnClick())
905 pSettingControl
->UpdateFromSetting();
908 void CGUIDialogSettingsBase::UpdateSettingControl(const std::string
& settingId
,
909 bool updateDisplayOnly
/* = false */)
911 if (settingId
.empty())
914 return UpdateSettingControl(GetSettingControl(settingId
), updateDisplayOnly
);
917 void CGUIDialogSettingsBase::UpdateSettingControl(const BaseSettingControlPtr
& pSettingControl
,
918 bool updateDisplayOnly
/* = false */)
920 if (pSettingControl
== NULL
)
923 // we send a thread message so that it's processed the following frame (some settings won't
924 // like being changed during Render())
925 // param2 = 1 for "only update the current value"
926 CGUIMessage
message(GUI_MSG_UPDATE_ITEM
, GetID(), pSettingControl
->GetID(), 0,
927 updateDisplayOnly
? 1 : 0);
928 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message
, GetID());
931 void CGUIDialogSettingsBase::SetControlLabel(int controlId
, const CVariant
& label
)
933 if (GetControl(controlId
) == NULL
)
936 if (label
.isString())
937 SET_CONTROL_LABEL(controlId
, label
.asString());
938 else if (label
.isInteger() && label
.asInteger() >= 0)
940 int labelId
= static_cast<uint32_t>(label
.asInteger());
941 std::string localizedString
= GetLocalizedString(labelId
);
942 if (!localizedString
.empty())
943 SET_CONTROL_LABEL(controlId
, localizedString
);
945 SET_CONTROL_LABEL(controlId
, labelId
);
948 SET_CONTROL_LABEL(controlId
, "");
951 BaseSettingControlPtr
CGUIDialogSettingsBase::GetSettingControl(const std::string
& strSetting
)
953 for (std::vector
<BaseSettingControlPtr
>::iterator control
= m_settingControls
.begin();
954 control
!= m_settingControls
.end(); ++control
)
956 if ((*control
)->GetSetting() != NULL
&& (*control
)->GetSetting()->GetId() == strSetting
)
960 return BaseSettingControlPtr();
963 BaseSettingControlPtr
CGUIDialogSettingsBase::GetSettingControl(int controlId
)
965 if (controlId
< CONTROL_SETTINGS_START_CONTROL
||
966 controlId
>= (int)(CONTROL_SETTINGS_START_CONTROL
+ m_settingControls
.size()))
967 return BaseSettingControlPtr();
969 return m_settingControls
[controlId
- CONTROL_SETTINGS_START_CONTROL
];