[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / settings / dialogs / GUIDialogSettingsBase.cpp
blob1d878dbb2d580f663801d00738085af727429008
1 /*
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.
7 */
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"
34 #include <memory>
35 #include <set>
36 #include <string>
37 #include <vector>
39 #if defined(TARGET_WINDOWS) // disable 4355: 'this' used in base member initializer list
40 #pragma warning(push)
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),
59 m_resetSetting(NULL),
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),
69 m_delayedTimer(this)
71 m_loadType = KEEP_IN_MEMORY;
74 CGUIDialogSettingsBase::~CGUIDialogSettingsBase()
76 FreeControls();
77 DeleteControls();
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
90 m_iCategory = 0;
91 ResetControlStates();
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);
105 break;
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());
115 OnMessage(message);
118 CGUIDialog::OnMessage(message);
119 FreeControls();
120 return true;
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);
164 return false;
167 m_iCategory = categoryIndex;
168 CreateSettings();
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();
178 if (setting != NULL)
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);
186 return true;
189 case GUI_MSG_CLICKED:
191 int iControl = message.GetSenderId();
192 if (iControl == CONTROL_SETTINGS_OKAY_BUTTON)
194 if (OnOkay())
196 Close();
197 return true;
200 return false;
203 if (iControl == CONTROL_SETTINGS_CANCEL_BUTTON)
205 OnCancel();
206 Close();
207 return true;
210 BaseSettingControlPtr control = GetSettingControl(iControl);
211 if (control != NULL)
212 OnClick(control);
214 break;
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
230 // setting control
231 if (!delayedSetting->OnClick() && message.GetParam1() != 0)
232 OnSettingChanged(delayedSetting->GetSetting());
233 return true;
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);
243 return true;
246 break;
249 case GUI_MSG_UPDATE:
251 if (IsActive() && HasID(message.GetSenderId()))
253 int focusedControl = GetFocusedControlID();
254 CreateSettings();
255 SET_CONTROL_FOCUS(focusedControl, 0);
257 break;
260 default:
261 break;
264 return CGUIDialog::OnMessage(message);
267 bool CGUIDialogSettingsBase::OnAction(const CAction& action)
269 switch (action.GetID())
271 case ACTION_SETTINGS_RESET:
273 OnResetSettings();
274 return true;
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)
288 setting->Reset();
289 return true;
293 break;
296 default:
297 break;
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
308 if (!IsDialog())
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);
318 if (control)
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);
325 else
326 static_cast<CGUIButtonControl*>(control)->SetSelected(false);
327 m_fadedControl = 0;
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);
337 else
338 m_fadedControl = 0;
340 if (m_fadedControl)
341 control->SetFocus(true);
344 CGUIDialog::DoProcess(currentTime, dirtyregions);
347 void CGUIDialogSettingsBase::OnInitWindow()
349 m_confirmed = false;
350 SetupView();
351 CGUIDialog::OnInitWindow();
354 void CGUIDialogSettingsBase::SetupControls(bool createSettings /* = true */)
356 // cleanup first, if necessary
357 FreeControls();
359 // get all controls
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);
401 // get the section
402 SettingSectionPtr section = GetSection();
403 if (section == NULL)
404 return;
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));
420 if (!group)
421 return;
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));
435 else
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);
443 buttonIdOffset++;
447 if (createSettings)
448 CreateSettings();
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));
463 if (control)
465 control->FreeResources();
466 control->ClearAll();
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));
492 if (control)
494 control->FreeResources();
495 control->ClearAll();
498 for (std::vector<BaseSettingControlPtr>::iterator control = m_settingControls.begin();
499 control != m_settingControls.end(); ++control)
500 (*control)->Clear();
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)
514 return;
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)
523 return;
525 UpdateSettingControl(setting->GetId());
528 std::string CGUIDialogSettingsBase::GetLocalizedString(uint32_t labelId) const
530 return g_localizeStrings.Get(labelId);
533 void CGUIDialogSettingsBase::SetupView()
535 SetupControls();
538 std::set<std::string> CGUIDialogSettingsBase::CreateSettings()
540 FreeSettingsControls();
542 std::set<std::string> settingMap;
544 if (m_categories.size() <= 0)
545 return settingMap;
547 if (m_iCategory < 0 || m_iCategory >= (int)m_categories.size())
548 m_iCategory = 0;
550 CGUIControlGroupList* group = dynamic_cast<CGUIControlGroupList*>(GetControl(SETTINGS_GROUP_ID));
551 if (group == NULL)
552 return settingMap;
554 SettingCategoryPtr category = m_categories.at(m_iCategory);
555 if (category == NULL)
556 return settingMap;
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;
563 bool first = true;
564 for (SettingGroupList::const_iterator groupIt = groups.begin(); groupIt != groups.end();
565 ++groupIt)
567 if (*groupIt == NULL)
568 continue;
570 const SettingList& settings = (*groupIt)->GetSettings((SettingLevel)GetSettingLevel());
571 if (settings.size() <= 0)
572 continue;
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)
582 if (first)
584 first = false;
585 if (groupLabel <= 0)
586 hideSeparator = true;
588 else if (!separatorBelowGroupLabel && !hideSeparator)
589 AddSeparator(group->GetWidth(), iControlID);
591 if (groupLabel > 0)
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();
598 ++settingIt)
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)
614 UpdateSettings();
616 group->SetInvalid();
618 return settingMap;
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)
635 continue;
637 pSettingControl->UpdateFromSetting();
641 CGUIControl* CGUIDialogSettingsBase::AddSetting(const std::shared_ptr<CSetting>& pSetting,
642 float width,
643 int& iControlID)
645 if (pSetting == NULL)
646 return 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)
657 parentLevels++;
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())
672 return NULL;
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)
680 return 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)
691 return 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)
702 return 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)
713 return 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)
727 return NULL;
729 static_cast<CGUIButtonControl*>(pControl)->SetLabel(label);
730 pSettingControl = std::make_shared<CGUIControlButtonSetting>(
731 static_cast<CGUIButtonControl*>(pControl), iControlID, pSetting, this);
733 else
735 if (m_pOriginalSlider != NULL)
736 pControl = m_pOriginalSlider->Clone();
737 if (pControl == NULL)
738 return 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)
750 return 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)
761 return 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)
772 return nullptr;
774 static_cast<CGUIColorButtonControl*>(pControl)->SetLabel(label);
775 pSettingControl = std::make_shared<CGUIControlColorButtonSetting>(
776 static_cast<CGUIColorButtonControl*>(pControl), iControlID, pSetting, this);
778 else
779 return nullptr;
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)
790 return NULL;
792 CGUIControl* pControl = new CGUIImage(*m_pOriginalImage);
793 if (pControl == NULL)
794 return NULL;
796 return AddSettingControl(pControl,
797 BaseSettingControlPtr(new CGUIControlSeparatorSetting(
798 static_cast<CGUIImage*>(pControl), iControlID, this)),
799 width, iControlID);
802 CGUIControl* CGUIDialogSettingsBase::AddGroupLabel(const std::shared_ptr<CSettingGroup>& group,
803 float width,
804 int& iControlID)
806 if (m_pOriginalGroupTitle == NULL)
807 return NULL;
809 CGUIControl* pControl = new CGUILabelControl(*m_pOriginalGroupTitle);
810 if (pControl == NULL)
811 return NULL;
813 static_cast<CGUILabelControl*>(pControl)->SetLabel(GetSettingsLabel(group));
815 return AddSettingControl(pControl,
816 BaseSettingControlPtr(new CGUIControlGroupTitleSetting(
817 static_cast<CGUILabelControl*>(pControl), iControlID, this)),
818 width, iControlID);
821 CGUIControl* CGUIDialogSettingsBase::AddSettingControl(CGUIControl* pControl,
822 BaseSettingControlPtr pSettingControl,
823 float width,
824 int& iControlID)
826 if (pControl == NULL)
828 pSettingControl.reset();
829 return NULL;
832 pControl->SetID(iControlID++);
833 pControl->SetVisible(true);
834 pControl->SetWidth(width);
836 CGUIControlGroupList* group = dynamic_cast<CGUIControlGroupList*>(GetControl(SETTINGS_GROUP_ID));
837 if (group != NULL)
839 pControl->AllocResources();
840 group->AddControl(pControl);
842 m_settingControls.push_back(pSettingControl);
844 return pControl;
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();
865 if (setting != NULL)
866 setting->Reset();
871 void CGUIDialogSettingsBase::OnClick(const BaseSettingControlPtr& pSettingControl)
873 if (AllowResettingSettings() &&
874 pSettingControl->GetSetting()->GetId() == SETTINGS_RESET_SETTING_ID)
876 OnAction(CAction(ACTION_SETTINGS_RESET));
877 return;
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();
896 else
897 m_delayedTimer.Start(GetDelayMs());
899 return;
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())
912 return;
914 return UpdateSettingControl(GetSettingControl(settingId), updateDisplayOnly);
917 void CGUIDialogSettingsBase::UpdateSettingControl(const BaseSettingControlPtr& pSettingControl,
918 bool updateDisplayOnly /* = false */)
920 if (pSettingControl == NULL)
921 return;
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)
934 return;
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);
944 else
945 SET_CONTROL_LABEL(controlId, labelId);
947 else
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)
957 return *control;
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];