2 * Copyright (C) 2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
24 #include "SettingDefinitions.h"
25 #include "SettingsManager.h"
26 #include "utils/log.h"
27 #include "utils/StringUtils.h"
28 #include "utils/XBMCTinyXML.h"
29 #include "utils/XMLUtils.h"
31 CSetting::CSetting(const std::string &id, CSettingsManager *settingsManager /* = NULL */)
32 : ISetting(id, settingsManager),
34 m_label(-1), m_help(-1),
35 m_level(SettingLevelStandard),
40 CSetting::CSetting(const std::string &id, const CSetting &setting)
41 : ISetting(id, setting.m_settingsManager),
43 m_label(-1), m_help(-1),
44 m_level(SettingLevelStandard),
57 bool CSetting::Deserialize(const TiXmlNode *node, bool update /* = false */)
59 // handle <visible> conditions
60 if (!ISetting::Deserialize(node, update))
63 const TiXmlElement *element = node->ToElement();
67 // get the attributes label and help
69 if (element->QueryIntAttribute(SETTING_XML_ATTR_LABEL, &tmp) == TIXML_SUCCESS && tmp > 0)
73 if (element->QueryIntAttribute(SETTING_XML_ATTR_HELP, &tmp) == TIXML_SUCCESS && tmp > 0)
75 const char *parentSetting = element->Attribute(SETTING_XML_ATTR_PARENT);
76 if (parentSetting != NULL)
77 m_parentSetting = parentSetting;
81 if (XMLUtils::GetInt(node, SETTING_XML_ELM_LEVEL, level))
82 m_level = (SettingLevel)level;
84 if (m_level < (int)SettingLevelBasic || m_level > (int)SettingLevelInternal)
85 m_level = SettingLevelStandard;
87 const TiXmlNode *dependencies = node->FirstChild(SETTING_XML_ELM_DEPENDENCIES);
88 if (dependencies != NULL)
90 const TiXmlNode *dependencyNode = dependencies->FirstChild(SETTING_XML_ELM_DEPENDENCY);
91 while (dependencyNode != NULL)
93 CSettingDependency dependency(m_settingsManager);
94 if (dependency.Deserialize(dependencyNode))
95 m_dependencies.push_back(dependency);
97 CLog::Log(LOGWARNING, "CSetting: error reading <dependency> tag of \"%s\"", m_id.c_str());
99 dependencyNode = dependencyNode->NextSibling(SETTING_XML_ELM_DEPENDENCY);
103 const TiXmlElement *control = node->FirstChildElement(SETTING_XML_ELM_CONTROL);
106 const char *controlType = control->Attribute(SETTING_XML_ATTR_TYPE);
107 if (controlType == NULL)
109 CLog::Log(LOGERROR, "CSetting: error reading \"type\" attribute of <control> tag of \"%s\"", m_id.c_str());
113 m_control = m_settingsManager->CreateControl(controlType);
114 if (m_control == NULL || !m_control->Deserialize(control, update))
116 CLog::Log(LOGERROR, "CSetting: error reading <control> tag of \"%s\"", m_id.c_str());
120 else if (!update && m_level < SettingLevelInternal)
122 CLog::Log(LOGERROR, "CSetting: missing <control> tag of \"%s\"", m_id.c_str());
126 const TiXmlNode *updates = node->FirstChild(SETTING_XML_ELM_UPDATES);
129 const TiXmlElement *updateElem = updates->FirstChildElement(SETTING_XML_ELM_UPDATE);
130 while (updateElem != NULL)
132 CSettingUpdate update;
133 if (update.Deserialize(updateElem))
135 if (!m_updates.insert(update).second)
136 CLog::Log(LOGWARNING, "CSetting: duplicate <update> definition for \"%s\"", m_id.c_str());
139 CLog::Log(LOGWARNING, "CSetting: error reading <update> tag of \"%s\"", m_id.c_str());
141 updateElem = updateElem->NextSiblingElement(SETTING_XML_ELM_UPDATE);
148 bool CSetting::IsEnabled() const
151 for (SettingDependencies::const_iterator depIt = m_dependencies.begin(); depIt != m_dependencies.end(); ++depIt)
153 if (depIt->GetType() != SettingDependencyTypeEnable)
166 bool CSetting::IsVisible() const
168 if (!ISetting::IsVisible())
172 for (SettingDependencies::const_iterator depIt = m_dependencies.begin(); depIt != m_dependencies.end(); ++depIt)
174 if (depIt->GetType() != SettingDependencyTypeVisible)
187 bool CSetting::OnSettingChanging(const CSetting *setting)
189 if (m_callback == NULL)
192 return m_callback->OnSettingChanging(setting);
195 void CSetting::OnSettingChanged(const CSetting *setting)
197 if (m_callback == NULL)
200 m_callback->OnSettingChanged(setting);
203 void CSetting::OnSettingAction(const CSetting *setting)
205 if (m_callback == NULL)
208 m_callback->OnSettingAction(setting);
211 bool CSetting::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
213 if (m_callback == NULL)
216 return m_callback->OnSettingUpdate(setting, oldSettingId, oldSettingNode);
219 void CSetting::OnSettingPropertyChanged(const CSetting *setting, const char *propertyName)
221 if (m_callback == NULL)
224 m_callback->OnSettingPropertyChanged(setting, propertyName);
227 void CSetting::Copy(const CSetting &setting)
229 SetVisible(setting.IsVisible());
230 SetRequirementsMet(setting.MeetsRequirements());
231 m_callback = setting.m_callback;
232 m_label = setting.m_label;
233 m_help = setting.m_help;
234 m_level = setting.m_level;
237 if (setting.m_control != NULL)
239 m_control = m_settingsManager->CreateControl(setting.m_control->GetType());
240 *m_control = *setting.m_control;
245 m_dependencies = setting.m_dependencies;
246 m_updates = setting.m_updates;
247 m_changed = setting.m_changed;
250 CSettingList::CSettingList(const std::string &id, CSetting *settingDefinition, CSettingsManager *settingsManager /* = NULL */)
251 : CSetting(id, settingsManager),
252 m_definition(settingDefinition),
254 m_minimumItems(0), m_maximumItems(-1)
257 CSettingList::CSettingList(const std::string &id, const CSettingList &setting)
258 : CSetting(id, setting),
261 m_minimumItems(0), m_maximumItems(-1)
266 CSettingList::~CSettingList()
273 CSetting* CSettingList::Clone(const std::string &id) const
275 if (m_definition == NULL)
278 return new CSettingList(id, *this);
281 bool CSettingList::Deserialize(const TiXmlNode *node, bool update /* = false */)
283 CExclusiveLock lock(m_critical);
285 if (m_definition == NULL)
288 if (!CSetting::Deserialize(node, update))
291 const TiXmlElement *element = node->ToElement();
294 CLog::Log(LOGWARNING, "CSettingList: unable to read type of list setting of %s", m_id.c_str());
298 if (!m_definition->Deserialize(node, update))
301 const TiXmlNode *constraints = node->FirstChild(SETTING_XML_ELM_CONSTRAINTS);
302 if (constraints != NULL)
304 // read the delimiter
305 std::string delimiter;
306 if (XMLUtils::GetString(constraints, SETTING_XML_ELM_DELIMITER, delimiter) && !delimiter.empty())
307 m_delimiter = delimiter;
309 XMLUtils::GetInt(constraints, SETTING_XML_ELM_MINIMUM_ITEMS, m_minimumItems);
310 if (m_minimumItems < 0)
312 XMLUtils::GetInt(constraints, SETTING_XML_ELM_MAXIMUM_ITEMS, m_maximumItems);
313 if (m_maximumItems <= 0)
315 else if (m_maximumItems < m_minimumItems)
317 CLog::Log(LOGWARNING, "CSettingList: invalid <minimum> (%d) and/or <maximum> (%d) of %s", m_minimumItems, m_maximumItems, m_id.c_str());
322 // read the default and initial values
324 if (XMLUtils::GetString(node, SETTING_XML_ELM_DEFAULT, values))
326 if (!fromString(values, m_defaults))
328 CLog::Log(LOGWARNING, "CSettingList: invalid <default> definition \"%s\" of %s", values.c_str(), m_id.c_str());
337 int CSettingList::GetElementType() const
339 CSharedLock lock(m_critical);
341 if (m_definition == NULL)
342 return SettingTypeNone;
344 return m_definition->GetType();
347 bool CSettingList::FromString(const std::string &value)
349 SettingPtrList values;
350 if (!fromString(value, values))
353 return SetValue(values);
356 std::string CSettingList::ToString() const
358 return toString(m_values);
361 bool CSettingList::Equals(const std::string &value) const
363 SettingPtrList values;
364 if (!fromString(value, values) ||
365 values.size() != m_values.size())
369 for (size_t index = 0; index < values.size(); index++)
371 if (!m_values[index]->Equals(values[index]->ToString()))
381 bool CSettingList::CheckValidity(const std::string &value) const
383 SettingPtrList values;
384 return fromString(value, values);
387 void CSettingList::Reset()
389 CExclusiveLock lock(m_critical);
390 SettingPtrList values;
391 for (SettingPtrList::const_iterator it = m_defaults.begin(); it != m_defaults.end(); ++it)
392 values.push_back(SettingPtr((*it)->Clone((*it)->GetId())));
397 bool CSettingList::FromString(const std::vector<std::string> &value)
399 SettingPtrList values;
400 if (!fromValues(value, values))
403 return SetValue(values);
406 bool CSettingList::SetValue(const SettingPtrList &values)
408 CExclusiveLock lock(m_critical);
410 if ((int)values.size() < m_minimumItems ||
411 (m_maximumItems > 0 && (int)values.size() > m_maximumItems))
414 bool equal = values.size() == m_values.size();
415 for (size_t index = 0; index < values.size(); index++)
417 if (values[index]->GetType() != GetElementType())
421 !values[index]->Equals(m_values[index]->ToString()))
428 SettingPtrList oldValues = m_values;
430 m_values.insert(m_values.begin(), values.begin(), values.end());
432 if (!OnSettingChanging(this))
434 m_values = oldValues;
436 // the setting couldn't be changed because one of the
437 // callback handlers failed the OnSettingChanging()
438 // callback so we need to let all the callback handlers
439 // know that the setting hasn't changed
440 OnSettingChanging(this);
444 m_changed = (toString(m_values) == toString(m_defaults));
445 OnSettingChanged(this);
449 void CSettingList::SetDefault(const SettingPtrList &values)
451 CExclusiveLock lock(m_critical);
454 m_defaults.insert(m_defaults.begin(), values.begin(), values.end());
459 for (SettingPtrList::const_iterator it = m_defaults.begin(); it != m_defaults.end(); ++it)
460 m_values.push_back(SettingPtr((*it)->Clone((*it)->GetId())));
464 void CSettingList::copy(const CSettingList &setting)
466 CSetting::Copy(setting);
468 copy(setting.m_values, m_values);
469 copy(setting.m_defaults, m_defaults);
471 if (setting.m_definition != NULL)
473 CSetting *definitionCopy = setting.m_definition->Clone(m_id + ".definition");
474 if (definitionCopy != NULL)
475 m_definition = definitionCopy;
478 m_delimiter = setting.m_delimiter;
479 m_minimumItems = setting.m_minimumItems;
480 m_maximumItems = setting.m_maximumItems;
483 void CSettingList::copy(const SettingPtrList &srcValues, SettingPtrList &dstValues)
487 for (SettingPtrList::const_iterator itValue = srcValues.begin(); itValue != srcValues.end(); ++itValue)
489 if (*itValue == NULL)
492 CSetting *valueCopy = (*itValue)->Clone((*itValue)->GetId());
493 if (valueCopy == NULL)
496 dstValues.push_back(SettingPtr(valueCopy));
500 bool CSettingList::fromString(const std::string &strValue, SettingPtrList &values) const
502 std::vector<std::string> strValues = StringUtils::Split(strValue, m_delimiter);
503 return fromValues(strValues, values);
506 bool CSettingList::fromValues(const std::vector<std::string> &strValues, SettingPtrList &values) const
508 if ((int)strValues.size() < m_minimumItems ||
509 (m_maximumItems > 0 && (int)strValues.size() > m_maximumItems))
514 for (std::vector<std::string>::const_iterator itValue = strValues.begin(); itValue != strValues.end(); ++itValue)
516 CSetting *settingValue = m_definition->Clone(StringUtils::Format("%s.%d", m_id.c_str(), index++));
517 if (settingValue == NULL ||
518 !settingValue->FromString(*itValue))
525 values.push_back(SettingPtr(settingValue));
534 std::string CSettingList::toString(const SettingPtrList &values) const
536 std::vector<std::string> strValues;
537 for (SettingPtrList::const_iterator it = values.begin(); it != values.end(); ++it)
540 strValues.push_back((*it)->ToString());
543 return StringUtils::Join(strValues, m_delimiter);
546 CSettingBool::CSettingBool(const std::string &id, CSettingsManager *settingsManager /* = NULL */)
547 : CSetting(id, settingsManager),
548 m_value(false), m_default(false)
551 CSettingBool::CSettingBool(const std::string &id, const CSettingBool &setting)
552 : CSetting(id, setting)
557 CSettingBool::CSettingBool(const std::string &id, int label, bool value, CSettingsManager *settingsManager /* = NULL */)
558 : CSetting(id, settingsManager),
559 m_value(value), m_default(value)
564 CSetting* CSettingBool::Clone(const std::string &id) const
566 return new CSettingBool(id, *this);
569 bool CSettingBool::Deserialize(const TiXmlNode *node, bool update /* = false */)
571 CExclusiveLock lock(m_critical);
573 if (!CSetting::Deserialize(node, update))
576 // get the default value
578 if (XMLUtils::GetBoolean(node, SETTING_XML_ELM_DEFAULT, value))
579 m_value = m_default = value;
582 CLog::Log(LOGERROR, "CSettingBool: error reading the default value of \"%s\"", m_id.c_str());
589 bool CSettingBool::FromString(const std::string &value)
592 if (!fromString(value, bValue))
595 return SetValue(bValue);
598 std::string CSettingBool::ToString() const
600 return m_value ? "true" : "false";
603 bool CSettingBool::Equals(const std::string &value) const
606 return (fromString(value, bValue) && m_value == bValue);
609 bool CSettingBool::CheckValidity(const std::string &value) const
612 return fromString(value, bValue);
615 bool CSettingBool::SetValue(bool value)
617 CExclusiveLock lock(m_critical);
619 if (value == m_value)
622 bool oldValue = m_value;
625 if (!OnSettingChanging(this))
629 // the setting couldn't be changed because one of the
630 // callback handlers failed the OnSettingChanging()
631 // callback so we need to let all the callback handlers
632 // know that the setting hasn't changed
633 OnSettingChanging(this);
637 m_changed = m_value != m_default;
638 OnSettingChanged(this);
642 void CSettingBool::SetDefault(bool value)
644 CExclusiveLock lock(m_critical);
651 void CSettingBool::copy(const CSettingBool &setting)
653 CSetting::Copy(setting);
655 m_value = setting.m_value;
656 m_default = setting.m_default;
659 bool CSettingBool::fromString(const std::string &strValue, bool &value) const
661 if (StringUtils::EqualsNoCase(strValue, "true"))
666 if (StringUtils::EqualsNoCase(strValue, "false"))
675 CSettingInt::CSettingInt(const std::string &id, CSettingsManager *settingsManager /* = NULL */)
676 : CSetting(id, settingsManager),
677 m_value(0), m_default(0),
678 m_min(0), m_step(1), m_max(0)
681 CSettingInt::CSettingInt(const std::string &id, const CSettingInt &setting)
682 : CSetting(id, setting)
687 CSettingInt::CSettingInt(const std::string &id, int label, int value, int minimum, int step, int maximum, CSettingsManager *settingsManager /* = NULL */)
688 : CSetting(id, settingsManager),
689 m_value(value), m_default(value),
690 m_min(minimum), m_step(step), m_max(maximum)
695 CSettingInt::CSettingInt(const std::string &id, int label, int value, const StaticIntegerSettingOptions &options, CSettingsManager *settingsManager /* = NULL */)
696 : CSetting(id, settingsManager),
697 m_value(value), m_default(value),
698 m_min(0), m_step(1), m_max(0),
704 CSetting* CSettingInt::Clone(const std::string &id) const
706 return new CSettingInt(id, *this);
709 bool CSettingInt::Deserialize(const TiXmlNode *node, bool update /* = false */)
711 CExclusiveLock lock(m_critical);
713 if (!CSetting::Deserialize(node, update))
716 // get the default value
718 if (XMLUtils::GetInt(node, SETTING_XML_ELM_DEFAULT, value))
719 m_value = m_default = value;
722 CLog::Log(LOGERROR, "CSettingInt: error reading the default value of \"%s\"", m_id.c_str());
726 const TiXmlNode *constraints = node->FirstChild(SETTING_XML_ELM_CONSTRAINTS);
727 if (constraints != NULL)
730 const TiXmlNode *options = constraints->FirstChild(SETTING_XML_ELM_OPTIONS);
731 if (options != NULL && options->FirstChild() != NULL)
733 if (options->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT)
734 m_optionsFiller = options->FirstChild()->ValueStr();
738 const TiXmlElement *optionElement = options->FirstChildElement(SETTING_XML_ELM_OPTION);
739 while (optionElement != NULL)
741 std::pair<int, int> entry;
742 if (optionElement->QueryIntAttribute(SETTING_XML_ATTR_LABEL, &entry.first) == TIXML_SUCCESS && entry.first > 0)
744 entry.second = strtol(optionElement->FirstChild()->Value(), NULL, 10);
745 m_options.push_back(entry);
748 optionElement = optionElement->NextSiblingElement(SETTING_XML_ELM_OPTION);
754 XMLUtils::GetInt(constraints, SETTING_XML_ELM_MINIMUM, m_min);
756 XMLUtils::GetInt(constraints, SETTING_XML_ELM_STEP, m_step);
758 XMLUtils::GetInt(constraints, SETTING_XML_ELM_MAXIMUM, m_max);
764 bool CSettingInt::FromString(const std::string &value)
767 if (!fromString(value, iValue))
770 return SetValue(iValue);
773 std::string CSettingInt::ToString() const
775 std::ostringstream oss;
781 bool CSettingInt::Equals(const std::string &value) const
784 return (fromString(value, iValue) && m_value == iValue);
787 bool CSettingInt::CheckValidity(const std::string &value) const
790 if (!fromString(value, iValue))
793 return CheckValidity(iValue);
796 bool CSettingInt::CheckValidity(int value) const
798 if (!m_options.empty())
800 //if the setting is an std::map, check if we got a valid value before assigning it
802 for (StaticIntegerSettingOptions::const_iterator it = m_options.begin(); it != m_options.end(); ++it)
804 if (it->second == value)
814 else if (m_optionsFiller.empty() && m_min != m_max &&
815 (value < m_min || value > m_max))
821 bool CSettingInt::SetValue(int value)
823 CExclusiveLock lock(m_critical);
825 if (value == m_value)
828 if (!CheckValidity(value))
831 int oldValue = m_value;
834 if (!OnSettingChanging(this))
838 // the setting couldn't be changed because one of the
839 // callback handlers failed the OnSettingChanging()
840 // callback so we need to let all the callback handlers
841 // know that the setting hasn't changed
842 OnSettingChanging(this);
846 m_changed = m_value != m_default;
847 OnSettingChanged(this);
851 void CSettingInt::SetDefault(int value)
853 CExclusiveLock lock(m_critical);
860 SettingOptionsType CSettingInt::GetOptionsType() const
862 CSharedLock lock(m_critical);
863 if (!m_options.empty())
864 return SettingOptionsTypeStatic;
865 if (!m_optionsFiller.empty())
866 return SettingOptionsTypeDynamic;
868 return SettingOptionsTypeNone;
871 DynamicIntegerSettingOptions CSettingInt::UpdateDynamicOptions()
873 CExclusiveLock lock(m_critical);
874 DynamicIntegerSettingOptions options;
875 if (m_optionsFiller.empty() || m_settingsManager == NULL)
878 IntegerSettingOptionsFiller filler = (IntegerSettingOptionsFiller)m_settingsManager->GetSettingOptionsFiller(this);
882 int bestMatchingValue = m_value;
883 filler(this, options, bestMatchingValue);
885 if (bestMatchingValue != m_value)
886 SetValue(bestMatchingValue);
888 bool changed = m_dynamicOptions.size() != options.size();
891 for (size_t index = 0; index < options.size(); index++)
893 if (options[index].first.compare(m_dynamicOptions[index].first) != 0 ||
894 options[index].second != m_dynamicOptions[index].second)
904 m_dynamicOptions = options;
905 OnSettingPropertyChanged(this, "options");
911 void CSettingInt::copy(const CSettingInt &setting)
913 CSetting::Copy(setting);
915 CExclusiveLock lock(m_critical);
917 m_value = setting.m_value;
918 m_default = setting.m_default;
919 m_min = setting.m_min;
920 m_step = setting.m_step;
921 m_max = setting.m_max;
922 m_options = setting.m_options;
923 m_optionsFiller = setting.m_optionsFiller;
926 bool CSettingInt::fromString(const std::string &strValue, int &value)
928 if (strValue.empty())
932 value = (int)strtol(strValue.c_str(), &end, 10);
933 if (end != NULL && *end != '\0')
939 CSettingNumber::CSettingNumber(const std::string &id, CSettingsManager *settingsManager /* = NULL */)
940 : CSetting(id, settingsManager),
941 m_value(0.0), m_default(0.0),
942 m_min(0.0), m_step(1.0), m_max(0.0)
945 CSettingNumber::CSettingNumber(const std::string &id, const CSettingNumber &setting)
946 : CSetting(id, setting)
951 CSettingNumber::CSettingNumber(const std::string &id, int label, float value, float minimum, float step, float maximum, CSettingsManager *settingsManager /* = NULL */)
952 : CSetting(id, settingsManager),
953 m_value(value), m_default(value),
954 m_min(minimum), m_step(step), m_max(maximum)
959 CSetting* CSettingNumber::Clone(const std::string &id) const
961 return new CSettingNumber(id, *this);
964 bool CSettingNumber::Deserialize(const TiXmlNode *node, bool update /* = false */)
966 CExclusiveLock lock(m_critical);
968 if (!CSetting::Deserialize(node, update))
971 // get the default value
973 if (XMLUtils::GetDouble(node, SETTING_XML_ELM_DEFAULT, value))
974 m_value = m_default = value;
977 CLog::Log(LOGERROR, "CSettingNumber: error reading the default value of \"%s\"", m_id.c_str());
981 const TiXmlNode *constraints = node->FirstChild(SETTING_XML_ELM_CONSTRAINTS);
982 if (constraints != NULL)
984 // get the minimum value
985 XMLUtils::GetDouble(constraints, SETTING_XML_ELM_MINIMUM, m_min);
986 // get the step value
987 XMLUtils::GetDouble(constraints, SETTING_XML_ELM_STEP, m_step);
988 // get the maximum value
989 XMLUtils::GetDouble(constraints, SETTING_XML_ELM_MAXIMUM, m_max);
995 bool CSettingNumber::FromString(const std::string &value)
998 if (!fromString(value, dValue))
1001 return SetValue(dValue);
1004 std::string CSettingNumber::ToString() const
1006 std::ostringstream oss;
1012 bool CSettingNumber::Equals(const std::string &value) const
1015 CSharedLock lock(m_critical);
1016 return (fromString(value, dValue) && m_value == dValue);
1019 bool CSettingNumber::CheckValidity(const std::string &value) const
1022 if (!fromString(value, dValue))
1025 return CheckValidity(dValue);
1028 bool CSettingNumber::CheckValidity(double value) const
1030 CSharedLock lock(m_critical);
1031 if (m_min != m_max &&
1032 (value < m_min || value > m_max))
1038 bool CSettingNumber::SetValue(double value)
1040 CExclusiveLock lock(m_critical);
1042 if (value == m_value)
1045 if (!CheckValidity(value))
1048 double oldValue = m_value;
1051 if (!OnSettingChanging(this))
1055 // the setting couldn't be changed because one of the
1056 // callback handlers failed the OnSettingChanging()
1057 // callback so we need to let all the callback handlers
1058 // know that the setting hasn't changed
1059 OnSettingChanging(this);
1063 m_changed = m_value != m_default;
1064 OnSettingChanged(this);
1068 void CSettingNumber::SetDefault(double value)
1070 CExclusiveLock lock(m_critical);
1074 m_value = m_default;
1077 void CSettingNumber::copy(const CSettingNumber &setting)
1079 CSetting::Copy(setting);
1080 CExclusiveLock lock(m_critical);
1082 m_value = setting.m_value;
1083 m_default = setting.m_default;
1084 m_min = setting.m_min;
1085 m_step = setting.m_step;
1086 m_max = setting.m_max;
1089 bool CSettingNumber::fromString(const std::string &strValue, double &value)
1091 if (strValue.empty())
1095 value = strtod(strValue.c_str(), &end);
1096 if (end != NULL && *end != '\0')
1102 CSettingString::CSettingString(const std::string &id, CSettingsManager *settingsManager /* = NULL */)
1103 : CSetting(id, settingsManager),
1107 CSettingString::CSettingString(const std::string &id, const CSettingString &setting)
1108 : CSetting(id, setting)
1113 CSettingString::CSettingString(const std::string &id, int label, const std::string &value, CSettingsManager *settingsManager /* = NULL */)
1114 : CSetting(id, settingsManager),
1115 m_value(value), m_default(value),
1121 CSetting* CSettingString::Clone(const std::string &id) const
1123 return new CSettingString(id, *this);
1126 bool CSettingString::Deserialize(const TiXmlNode *node, bool update /* = false */)
1128 CExclusiveLock lock(m_critical);
1130 if (!CSetting::Deserialize(node, update))
1133 const TiXmlNode *constraints = node->FirstChild(SETTING_XML_ELM_CONSTRAINTS);
1134 if (constraints != NULL)
1136 // get allowempty (needs to be parsed before parsing the default value)
1137 XMLUtils::GetBoolean(constraints, SETTING_XML_ELM_ALLOWEMPTY, m_allowEmpty);
1140 const TiXmlNode *options = constraints->FirstChild(SETTING_XML_ELM_OPTIONS);
1141 if (options != NULL && options->FirstChild() != NULL &&
1142 options->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT)
1143 m_optionsFiller = options->FirstChild()->ValueStr();
1146 // get the default value
1148 if (XMLUtils::GetString(node, SETTING_XML_ELM_DEFAULT, value) &&
1149 (!value.empty() || m_allowEmpty))
1150 m_value = m_default = value;
1151 else if (!update && !m_allowEmpty)
1153 CLog::Log(LOGERROR, "CSettingString: error reading the default value of \"%s\"", m_id.c_str());
1160 bool CSettingString::CheckValidity(const std::string &value) const
1162 CSharedLock lock(m_critical);
1163 if (!m_allowEmpty && value.empty())
1169 bool CSettingString::SetValue(const std::string &value)
1171 CExclusiveLock lock(m_critical);
1173 if (value == m_value)
1176 if (!CheckValidity(value))
1179 std::string oldValue = m_value;
1182 if (!OnSettingChanging(this))
1186 // the setting couldn't be changed because one of the
1187 // callback handlers failed the OnSettingChanging()
1188 // callback so we need to let all the callback handlers
1189 // know that the setting hasn't changed
1190 OnSettingChanging(this);
1194 m_changed = m_value != m_default;
1195 OnSettingChanged(this);
1199 void CSettingString::SetDefault(const std::string &value)
1201 CSharedLock lock(m_critical);
1205 m_value = m_default;
1208 SettingOptionsType CSettingString::GetOptionsType() const
1210 CSharedLock lock(m_critical);
1211 if (!m_optionsFiller.empty())
1212 return SettingOptionsTypeDynamic;
1214 return SettingOptionsTypeNone;
1217 DynamicStringSettingOptions CSettingString::UpdateDynamicOptions()
1219 CExclusiveLock lock(m_critical);
1220 DynamicStringSettingOptions options;
1221 if (m_optionsFiller.empty() || m_settingsManager == NULL)
1224 StringSettingOptionsFiller filler = (StringSettingOptionsFiller)m_settingsManager->GetSettingOptionsFiller(this);
1228 std::string bestMatchingValue = m_value;
1229 filler(this, options, bestMatchingValue);
1231 if (bestMatchingValue != m_value)
1232 SetValue(bestMatchingValue);
1234 // check if the list of items has changed
1235 bool changed = m_dynamicOptions.size() != options.size();
1238 for (size_t index = 0; index < options.size(); index++)
1240 if (options[index].first.compare(m_dynamicOptions[index].first) != 0 ||
1241 options[index].second.compare(m_dynamicOptions[index].second) != 0)
1251 m_dynamicOptions = options;
1252 OnSettingPropertyChanged(this, "options");
1258 void CSettingString::copy(const CSettingString &setting)
1260 CSetting::Copy(setting);
1262 CExclusiveLock lock(m_critical);
1263 m_value = setting.m_value;
1264 m_default = setting.m_default;
1265 m_allowEmpty = setting.m_allowEmpty;
1268 CSettingAction::CSettingAction(const std::string &id, CSettingsManager *settingsManager /* = NULL */)
1269 : CSetting(id, settingsManager)
1272 CSettingAction::CSettingAction(const std::string &id, const CSettingAction &setting)
1273 : CSetting(id, setting)
1276 CSetting* CSettingAction::Clone(const std::string &id) const
1278 return new CSettingAction(id, *this);
1281 bool CSettingAction::Deserialize(const TiXmlNode *node, bool update /* = false */)
1283 CSharedLock lock(m_critical);
1285 if (!CSetting::Deserialize(node, update))