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/>.
21 #include "SettingsManager.h"
22 #include "SettingDefinitions.h"
23 #include "SettingSection.h"
25 #include "utils/log.h"
26 #include "utils/StringUtils.h"
27 #include "utils/XBMCTinyXML.h"
30 CSettingsManager::CSettingsManager()
31 : m_initialized(false), m_loaded(false)
34 CSettingsManager::~CSettingsManager()
36 // first clear all registered settings handler and subsettings
37 // implementations because we can't be sure that they are still valid
38 m_settingsHandlers.clear();
39 m_subSettings.clear();
40 m_settingCreators.clear();
41 m_settingControlCreators.clear();
46 bool CSettingsManager::Initialize(const TiXmlElement *root)
48 CExclusiveLock lock(m_critical);
49 CExclusiveLock settingsLock(m_settingsCritical);
50 if (m_initialized || root == NULL)
53 if (!StringUtils::EqualsNoCase(root->ValueStr(), SETTING_XML_ROOT))
55 CLog::Log(LOGERROR, "CSettingsManager: error reading settings definition: doesn't contain <settings> tag");
59 const TiXmlNode *sectionNode = root->FirstChild(SETTING_XML_ELM_SECTION);
60 while (sectionNode != NULL)
62 std::string sectionId;
63 if (CSettingSection::DeserializeIdentification(sectionNode, sectionId))
65 CSettingSection *section = NULL;
66 SettingSectionMap::iterator itSection = m_sections.find(sectionId);
67 bool update = (itSection != m_sections.end());
69 section = new CSettingSection(sectionId, this);
71 section = itSection->second;
73 if (section->Deserialize(sectionNode, update))
75 section->CheckRequirements();
77 m_sections[section->GetId()] = section;
79 // get all settings and add them to the settings map
80 for (SettingCategoryList::const_iterator categoryIt = section->GetCategories().begin(); categoryIt != section->GetCategories().end(); ++categoryIt)
82 (*categoryIt)->CheckRequirements();
83 for (SettingGroupList::const_iterator groupIt = (*categoryIt)->GetGroups().begin(); groupIt != (*categoryIt)->GetGroups().end(); ++groupIt)
85 (*groupIt)->CheckRequirements();
86 for (SettingList::const_iterator settingIt = (*groupIt)->GetSettings().begin(); settingIt != (*groupIt)->GetSettings().end(); ++settingIt)
88 (*settingIt)->CheckRequirements();
90 const std::string &settingId = (*settingIt)->GetId();
91 SettingMap::iterator setting = m_settings.find(settingId);
92 if (setting == m_settings.end())
94 Setting tmpSetting = { NULL };
95 std::pair<SettingMap::iterator, bool> tmpIt = m_settings.insert(make_pair(settingId, tmpSetting));
96 setting = tmpIt.first;
99 if (setting->second.setting == NULL)
101 setting->second.setting = *settingIt;
102 (*settingIt)->m_callback = this;
110 CLog::Log(LOGWARNING, "CSettingsManager: unable to read section \"%s\"", sectionId.c_str());
116 sectionNode = sectionNode->NextSibling(SETTING_XML_ELM_SECTION);
119 for (SettingMap::iterator itSettingDep = m_settings.begin(); itSettingDep != m_settings.end(); ++itSettingDep)
121 if (itSettingDep->second.setting == NULL)
124 const SettingDependencies& deps = itSettingDep->second.setting->GetDependencies();
125 for (SettingDependencies::const_iterator depIt = deps.begin(); depIt != deps.end(); ++depIt)
127 std::set<std::string> settingIds = depIt->GetSettings();
128 for (std::set<std::string>::const_iterator itSettingId = settingIds.begin(); itSettingId != settingIds.end(); ++itSettingId)
130 SettingMap::iterator setting = m_settings.find(*itSettingId);
131 if (setting == m_settings.end())
135 SettingDependencies &settingDeps = setting->second.dependencies[itSettingDep->first];
136 for (SettingDependencies::const_iterator itDeps = settingDeps.begin(); itDeps != settingDeps.end(); ++itDeps)
138 if (itDeps->GetType() == depIt->GetType())
146 settingDeps.push_back(*depIt);
154 bool CSettingsManager::Load(const TiXmlElement *root, bool &updated, bool triggerEvents /* = true */, std::map<std::string, CSetting*> *loadedSettings /* = NULL */)
156 CSharedLock lock(m_critical);
157 CExclusiveLock settingsLock(m_settingsCritical);
158 if (m_loaded || root == NULL)
161 if (triggerEvents && !OnSettingsLoading())
164 if (!Deserialize(root, loadedSettings))
168 // load any ISubSettings implementations
172 updated = UpdateSettings(root);
180 bool CSettingsManager::Save(TiXmlNode *root) const
182 CSharedLock lock(m_critical);
183 CSharedLock settingsLock(m_settingsCritical);
184 if (!m_initialized || root == NULL)
187 if (!OnSettingsSaving())
190 if (!Serialize(root))
192 CLog::Log(LOGERROR, "CSettingsManager: failed to save settings");
196 // save any ISubSettings implementations
197 for (std::set<ISubSettings*>::const_iterator it = m_subSettings.begin(); it != m_subSettings.end(); ++it)
199 if (!(*it)->Save(root))
208 void CSettingsManager::Unload()
210 CExclusiveLock lock(m_settingsCritical);
214 // needs to be set before calling CSetting::Reset() to avoid calls to
215 // OnSettingChanging() and OnSettingChanged()
218 for (SettingMap::iterator setting = m_settings.begin(); setting != m_settings.end(); ++setting)
219 setting->second.setting->Reset();
221 OnSettingsUnloaded();
224 void CSettingsManager::Clear()
226 CExclusiveLock lock(m_critical);
230 for (SettingSectionMap::iterator section = m_sections.begin(); section != m_sections.end(); ++section)
231 delete section->second;
236 for (std::set<ISubSettings*>::const_iterator it = m_subSettings.begin(); it != m_subSettings.end(); ++it)
239 m_initialized = false;
242 bool CSettingsManager::LoadSetting(const TiXmlNode *node, const std::string &settingId)
247 CSetting *setting = GetSetting(settingId);
251 return LoadSetting(node, setting);
254 void CSettingsManager::SetInitialized()
256 CExclusiveLock lock(m_settingsCritical);
260 m_initialized = true;
262 for (SettingMap::iterator setting = m_settings.begin(); setting != m_settings.end(); )
264 SettingMap::iterator tmpIterator = setting++;
265 if (tmpIterator->second.setting == NULL)
266 m_settings.erase(tmpIterator);
270 void CSettingsManager::RegisterCallback(ISettingCallback *callback, const std::set<std::string> &settingList)
272 CExclusiveLock lock(m_settingsCritical);
273 if (callback == NULL)
276 for (std::set<std::string>::const_iterator settingIt = settingList.begin(); settingIt != settingList.end(); ++settingIt)
278 std::string id = *settingIt;
279 StringUtils::ToLower(id);
281 SettingMap::iterator setting = m_settings.find(id);
282 if (setting == m_settings.end())
287 Setting tmpSetting = { NULL };
288 std::pair<SettingMap::iterator, bool> tmpIt = m_settings.insert(make_pair(id, tmpSetting));
289 setting = tmpIt.first;
292 setting->second.callbacks.insert(callback);
296 void CSettingsManager::UnregisterCallback(ISettingCallback *callback)
298 CExclusiveLock lock(m_settingsCritical);
299 for (SettingMap::iterator settingIt = m_settings.begin(); settingIt != m_settings.end(); ++settingIt)
300 settingIt->second.callbacks.erase(callback);
303 void CSettingsManager::RegisterSettingType(const std::string &settingType, ISettingCreator *settingCreator)
305 CExclusiveLock lock(m_critical);
306 if (settingType.empty() || settingCreator == NULL)
309 SettingCreatorMap::const_iterator creatorIt = m_settingCreators.find(settingType);
310 if (creatorIt == m_settingCreators.end())
311 m_settingCreators.insert(make_pair(settingType, settingCreator));
314 void CSettingsManager::RegisterSettingControl(const std::string &controlType, ISettingControlCreator *settingControlCreator)
316 if (controlType.empty() || settingControlCreator == NULL)
319 CExclusiveLock lock(m_critical);
320 SettingControlCreatorMap::const_iterator creatorIt = m_settingControlCreators.find(controlType);
321 if (creatorIt == m_settingControlCreators.end())
322 m_settingControlCreators.insert(make_pair(controlType, settingControlCreator));
325 void CSettingsManager::RegisterSettingsHandler(ISettingsHandler *settingsHandler)
327 if (settingsHandler == NULL)
330 CExclusiveLock lock(m_critical);
331 if (find(m_settingsHandlers.begin(), m_settingsHandlers.end(), settingsHandler) == m_settingsHandlers.end())
332 m_settingsHandlers.push_back(settingsHandler);
335 void CSettingsManager::UnregisterSettingsHandler(ISettingsHandler *settingsHandler)
337 if (settingsHandler == NULL)
340 CExclusiveLock lock(m_critical);
341 SettingsHandlers::iterator it = find(m_settingsHandlers.begin(), m_settingsHandlers.end(), settingsHandler);
342 if (it != m_settingsHandlers.end())
343 m_settingsHandlers.erase(it);
346 void CSettingsManager::RegisterSubSettings(ISubSettings *subSettings)
348 CExclusiveLock lock(m_critical);
349 if (subSettings == NULL)
352 m_subSettings.insert(subSettings);
355 void CSettingsManager::UnregisterSubSettings(ISubSettings *subSettings)
357 CExclusiveLock lock(m_critical);
358 if (subSettings == NULL)
361 m_subSettings.erase(subSettings);
364 void CSettingsManager::RegisterSettingOptionsFiller(const std::string &identifier, IntegerSettingOptionsFiller optionsFiller)
366 if (identifier.empty() || optionsFiller == NULL)
369 RegisterSettingOptionsFiller(identifier, (void*)optionsFiller, SettingOptionsFillerTypeInteger);
372 void CSettingsManager::RegisterSettingOptionsFiller(const std::string &identifier, StringSettingOptionsFiller optionsFiller)
374 if (identifier.empty() || optionsFiller == NULL)
377 RegisterSettingOptionsFiller(identifier, (void*)optionsFiller, SettingOptionsFillerTypeString);
380 void CSettingsManager::UnregisterSettingOptionsFiller(const std::string &identifier)
382 CExclusiveLock lock(m_critical);
383 m_optionsFillers.erase(identifier);
386 void* CSettingsManager::GetSettingOptionsFiller(const CSetting *setting)
388 CSharedLock lock(m_critical);
392 // get the option filler's identifier
394 if (setting->GetType() == SettingTypeInteger)
395 filler = ((const CSettingInt*)setting)->GetOptionsFiller();
396 else if (setting->GetType() == SettingTypeString)
397 filler = ((const CSettingString*)setting)->GetOptionsFiller();
402 // check if such an option filler is known
403 SettingOptionsFillerMap::const_iterator fillerIt = m_optionsFillers.find(filler);
404 if (fillerIt == m_optionsFillers.end())
407 if (fillerIt->second.filler == NULL)
410 // make sure the option filler's type matches the setting's type
411 switch (fillerIt->second.type)
413 case SettingOptionsFillerTypeInteger:
415 if (setting->GetType() != SettingTypeInteger)
421 case SettingOptionsFillerTypeString:
423 if (setting->GetType() != SettingTypeString)
433 return fillerIt->second.filler;
436 CSetting* CSettingsManager::GetSetting(const std::string &id) const
438 CSharedLock lock(m_settingsCritical);
442 std::string settingId = id;
443 StringUtils::ToLower(settingId);
445 SettingMap::const_iterator setting = m_settings.find(settingId);
446 if (setting != m_settings.end())
447 return setting->second.setting;
449 CLog::Log(LOGDEBUG, "CSettingsManager: requested setting (%s) was not found.", id.c_str());
453 std::vector<CSettingSection*> CSettingsManager::GetSections() const
455 CSharedLock lock(m_critical);
456 std::vector<CSettingSection*> sections;
457 for (SettingSectionMap::const_iterator sectionIt = m_sections.begin(); sectionIt != m_sections.end(); ++sectionIt)
458 sections.push_back(sectionIt->second);
463 CSettingSection* CSettingsManager::GetSection(const std::string §ion) const
465 CSharedLock lock(m_critical);
469 std::string sectionId = section;
470 StringUtils::ToLower(sectionId);
472 SettingSectionMap::const_iterator sectionIt = m_sections.find(sectionId);
473 if (sectionIt != m_sections.end())
474 return sectionIt->second;
476 CLog::Log(LOGDEBUG, "CSettingsManager: requested setting section (%s) was not found.", section.c_str());
480 SettingDependencyMap CSettingsManager::GetDependencies(const std::string &id) const
482 CSharedLock lock(m_settingsCritical);
483 SettingMap::const_iterator setting = m_settings.find(id);
484 if (setting == m_settings.end())
485 return SettingDependencyMap();
487 return setting->second.dependencies;
490 SettingDependencyMap CSettingsManager::GetDependencies(const CSetting *setting) const
493 return SettingDependencyMap();
495 return GetDependencies(setting->GetId());
498 bool CSettingsManager::GetBool(const std::string &id) const
500 CSharedLock lock(m_settingsCritical);
501 CSetting *setting = GetSetting(id);
502 if (setting == NULL || setting->GetType() != SettingTypeBool)
505 return ((CSettingBool*)setting)->GetValue();
508 bool CSettingsManager::SetBool(const std::string &id, bool value)
510 CSharedLock lock(m_settingsCritical);
511 CSetting *setting = GetSetting(id);
512 if (setting == NULL || setting->GetType() != SettingTypeBool)
515 return ((CSettingBool*)setting)->SetValue(value);
518 bool CSettingsManager::ToggleBool(const std::string &id)
520 CSharedLock lock(m_settingsCritical);
521 CSetting *setting = GetSetting(id);
522 if (setting == NULL || setting->GetType() != SettingTypeBool)
525 return SetBool(id, !((CSettingBool*)setting)->GetValue());
528 int CSettingsManager::GetInt(const std::string &id) const
530 CSharedLock lock(m_settingsCritical);
531 CSetting *setting = GetSetting(id);
532 if (setting == NULL || setting->GetType() != SettingTypeInteger)
535 return ((CSettingInt*)setting)->GetValue();
538 bool CSettingsManager::SetInt(const std::string &id, int value)
540 CSharedLock lock(m_settingsCritical);
541 CSetting *setting = GetSetting(id);
542 if (setting == NULL || setting->GetType() != SettingTypeInteger)
545 return ((CSettingInt*)setting)->SetValue(value);
548 double CSettingsManager::GetNumber(const std::string &id) const
550 CSharedLock lock(m_settingsCritical);
551 CSetting *setting = GetSetting(id);
552 if (setting == NULL || setting->GetType() != SettingTypeNumber)
555 return ((CSettingNumber*)setting)->GetValue();
558 bool CSettingsManager::SetNumber(const std::string &id, double value)
560 CSharedLock lock(m_settingsCritical);
561 CSetting *setting = GetSetting(id);
562 if (setting == NULL || setting->GetType() != SettingTypeNumber)
565 return ((CSettingNumber*)setting)->SetValue(value);
568 std::string CSettingsManager::GetString(const std::string &id) const
570 CSharedLock lock(m_settingsCritical);
571 CSetting *setting = GetSetting(id);
572 if (setting == NULL || setting->GetType() != SettingTypeString)
575 return ((CSettingString*)setting)->GetValue();
578 bool CSettingsManager::SetString(const std::string &id, const std::string &value)
580 CSharedLock lock(m_settingsCritical);
581 CSetting *setting = GetSetting(id);
582 if (setting == NULL || setting->GetType() != SettingTypeString)
585 return ((CSettingString*)setting)->SetValue(value);
588 std::vector< boost::shared_ptr<CSetting> > CSettingsManager::GetList(const std::string &id) const
590 CSharedLock lock(m_settingsCritical);
591 CSetting *setting = GetSetting(id);
592 if (setting == NULL || setting->GetType() != SettingTypeList)
593 return std::vector< boost::shared_ptr<CSetting> >();
595 return ((CSettingList*)setting)->GetValue();
598 bool CSettingsManager::SetList(const std::string &id, const std::vector< boost::shared_ptr<CSetting> > &value)
600 CSharedLock lock(m_settingsCritical);
601 CSetting *setting = GetSetting(id);
602 if (setting == NULL || setting->GetType() != SettingTypeList)
605 return ((CSettingList*)setting)->SetValue(value);
608 void CSettingsManager::AddCondition(const std::string &condition)
610 CExclusiveLock lock(m_critical);
611 if (condition.empty())
614 m_conditions.AddCondition(condition);
617 void CSettingsManager::AddCondition(const std::string &identifier, SettingConditionCheck condition)
619 CExclusiveLock lock(m_critical);
620 if (identifier.empty() || condition == NULL)
623 m_conditions.AddCondition(identifier, condition);
626 bool CSettingsManager::Serialize(TiXmlNode *parent) const
631 CSharedLock lock(m_settingsCritical);
633 for (SettingMap::const_iterator it = m_settings.begin(); it != m_settings.end(); ++it)
635 if (it->second.setting->GetType() == SettingTypeAction)
638 std::vector<std::string> parts = StringUtils::Split(it->first, ".");
639 if (parts.size() != 2 || parts.at(0).empty() || parts.at(1).empty())
641 CLog::Log(LOGWARNING, "CSettingsManager: unable to save setting \"%s\"", it->first.c_str());
645 TiXmlNode *sectionNode = parent->FirstChild(parts.at(0));
646 if (sectionNode == NULL)
648 TiXmlElement sectionElement(parts.at(0));
649 sectionNode = parent->InsertEndChild(sectionElement);
651 if (sectionNode == NULL)
653 CLog::Log(LOGWARNING, "CSettingsManager: unable to write <%s> tag", parts.at(0).c_str());
658 TiXmlElement settingElement(parts.at(1));
659 TiXmlNode *settingNode = sectionNode->InsertEndChild(settingElement);
660 if (settingNode == NULL)
662 CLog::Log(LOGWARNING, "CSetting: unable to write <%s> tag in <%s>", parts.at(1).c_str(), parts.at(0).c_str());
666 TiXmlText value(it->second.setting->ToString());
667 settingNode->InsertEndChild(value);
673 bool CSettingsManager::Deserialize(const TiXmlNode *node, std::map<std::string, CSetting*> *loadedSettings /* = NULL */)
678 CSharedLock lock(m_settingsCritical);
680 for (SettingMap::iterator it = m_settings.begin(); it != m_settings.end(); ++it)
682 if (LoadSetting(node, it->second.setting) && loadedSettings != NULL)
683 loadedSettings->insert(make_pair(it->first, it->second.setting));
689 bool CSettingsManager::OnSettingChanging(const CSetting *setting)
694 CSharedLock lock(m_settingsCritical);
698 SettingMap::const_iterator settingIt = m_settings.find(setting->GetId());
699 if (settingIt == m_settings.end())
702 Setting settingData = settingIt->second;
703 // now that we have a copy of the setting's data, we can leave the lock
706 for (CallbackSet::iterator callback = settingData.callbacks.begin();
707 callback != settingData.callbacks.end();
710 if (!(*callback)->OnSettingChanging(setting))
717 void CSettingsManager::OnSettingChanged(const CSetting *setting)
719 CSharedLock lock(m_settingsCritical);
720 if (!m_loaded || setting == NULL)
723 SettingMap::const_iterator settingIt = m_settings.find(setting->GetId());
724 if (settingIt == m_settings.end())
727 Setting settingData = settingIt->second;
728 // now that we have a copy of the setting's data, we can leave the lock
731 for (CallbackSet::iterator callback = settingData.callbacks.begin();
732 callback != settingData.callbacks.end();
734 (*callback)->OnSettingChanged(setting);
736 // now handle any settings which depend on the changed setting
737 const SettingDependencyMap& deps = GetDependencies(setting);
738 for (SettingDependencyMap::const_iterator depsIt = deps.begin(); depsIt != deps.end(); ++depsIt)
740 for (SettingDependencies::const_iterator depIt = depsIt->second.begin(); depIt != depsIt->second.end(); ++depIt)
741 UpdateSettingByDependency(depsIt->first, *depIt);
745 void CSettingsManager::OnSettingAction(const CSetting *setting)
747 CSharedLock lock(m_settingsCritical);
748 if (!m_loaded || setting == NULL)
751 SettingMap::const_iterator settingIt = m_settings.find(setting->GetId());
752 if (settingIt == m_settings.end())
755 Setting settingData = settingIt->second;
756 // now that we have a copy of the setting's data, we can leave the lock
759 for (CallbackSet::iterator callback = settingData.callbacks.begin();
760 callback != settingData.callbacks.end();
762 (*callback)->OnSettingAction(setting);
765 bool CSettingsManager::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
767 CSharedLock lock(m_settingsCritical);
771 SettingMap::const_iterator settingIt = m_settings.find(setting->GetId());
772 if (settingIt == m_settings.end())
775 Setting settingData = settingIt->second;
776 // now that we have a copy of the setting's data, we can leave the lock
780 for (CallbackSet::iterator callback = settingData.callbacks.begin();
781 callback != settingData.callbacks.end();
783 ret |= (*callback)->OnSettingUpdate(setting, oldSettingId, oldSettingNode);
788 void CSettingsManager::OnSettingPropertyChanged(const CSetting *setting, const char *propertyName)
790 CSharedLock lock(m_settingsCritical);
791 if (!m_loaded || setting == NULL)
794 SettingMap::const_iterator settingIt = m_settings.find(setting->GetId());
795 if (settingIt == m_settings.end())
798 Setting settingData = settingIt->second;
799 // now that we have a copy of the setting's data, we can leave the lock
802 for (CallbackSet::iterator callback = settingData.callbacks.begin();
803 callback != settingData.callbacks.end();
805 (*callback)->OnSettingPropertyChanged(setting, propertyName);
808 CSetting* CSettingsManager::CreateSetting(const std::string &settingType, const std::string &settingId, CSettingsManager *settingsManager /* = NULL */) const
810 if (StringUtils::EqualsNoCase(settingType, "boolean"))
811 return new CSettingBool(settingId, const_cast<CSettingsManager*>(this));
812 else if (StringUtils::EqualsNoCase(settingType, "integer"))
813 return new CSettingInt(settingId, const_cast<CSettingsManager*>(this));
814 else if (StringUtils::EqualsNoCase(settingType, "number"))
815 return new CSettingNumber(settingId, const_cast<CSettingsManager*>(this));
816 else if (StringUtils::EqualsNoCase(settingType, "string"))
817 return new CSettingString(settingId, const_cast<CSettingsManager*>(this));
818 else if (StringUtils::EqualsNoCase(settingType, "action"))
819 return new CSettingAction(settingId, const_cast<CSettingsManager*>(this));
820 else if (settingType.size() > 6 &&
821 StringUtils::StartsWith(settingType, "list[") &&
822 StringUtils::EndsWith(settingType, "]"))
824 std::string elementType = StringUtils::Mid(settingType, 5, settingType.size() - 6);
825 CSetting *elementSetting = CreateSetting(elementType, settingId + ".definition", const_cast<CSettingsManager*>(this));
826 if (elementSetting != NULL)
827 return new CSettingList(settingId, elementSetting, const_cast<CSettingsManager*>(this));
830 CSharedLock lock(m_critical);
831 SettingCreatorMap::const_iterator creator = m_settingCreators.find(settingType);
832 if (creator != m_settingCreators.end())
833 return creator->second->CreateSetting(settingType, settingId, (CSettingsManager*)this);
838 ISettingControl* CSettingsManager::CreateControl(const std::string &controlType) const
840 if (controlType.empty())
843 CSharedLock lock(m_critical);
844 SettingControlCreatorMap::const_iterator creator = m_settingControlCreators.find(controlType);
845 if (creator != m_settingControlCreators.end() && creator->second != NULL)
846 return creator->second->CreateControl(controlType);
851 bool CSettingsManager::OnSettingsLoading()
853 CSharedLock lock(m_critical);
854 for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); ++it)
856 if (!(*it)->OnSettingsLoading())
863 void CSettingsManager::OnSettingsLoaded()
865 CSharedLock lock(m_critical);
866 for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); ++it)
867 (*it)->OnSettingsLoaded();
870 bool CSettingsManager::OnSettingsSaving() const
872 CSharedLock lock(m_critical);
873 for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); ++it)
875 if (!(*it)->OnSettingsSaving())
882 void CSettingsManager::OnSettingsSaved() const
884 CSharedLock lock(m_critical);
885 for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); ++it)
886 (*it)->OnSettingsSaved();
889 void CSettingsManager::OnSettingsCleared()
891 CSharedLock lock(m_critical);
892 for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); ++it)
893 (*it)->OnSettingsCleared();
896 bool CSettingsManager::Load(const TiXmlNode *settings)
899 CSharedLock lock(m_critical);
900 for (std::set<ISubSettings*>::const_iterator it = m_subSettings.begin(); it != m_subSettings.end(); ++it)
901 ok &= (*it)->Load(settings);
906 bool CSettingsManager::LoadSetting(const TiXmlNode *node, CSetting *setting)
908 if (node == NULL || setting == NULL)
911 if (setting->GetType() == SettingTypeAction)
914 const std::string &settingId = setting->GetId();
916 std::vector<std::string> parts = StringUtils::Split(settingId, ".");
917 if (parts.size() != 2 || parts.at(0).empty() || parts.at(1).empty())
919 CLog::Log(LOGWARNING, "CSettingsManager: unable to load setting \"%s\"", settingId.c_str());
923 const TiXmlNode *sectionNode = node->FirstChild(parts.at(0));
924 if (sectionNode == NULL)
927 const TiXmlNode *settingNode = sectionNode->FirstChild(parts.at(1));
928 if (settingNode == NULL)
931 if (!setting->FromString(settingNode->FirstChild() != NULL ? settingNode->FirstChild()->ValueStr() : StringUtils::Empty))
933 CLog::Log(LOGWARNING, "CSettingsManager: unable to read value of setting \"%s\"", settingId.c_str());
940 bool CSettingsManager::UpdateSettings(const TiXmlNode *root)
942 bool updated = false;
943 CSharedLock lock(m_settingsCritical);
945 for (SettingMap::iterator setting = m_settings.begin(); setting != m_settings.end(); ++setting)
947 const std::set<CSettingUpdate>& updates = setting->second.setting->GetUpdates();
951 for (std::set<CSettingUpdate>::const_iterator update = updates.begin(); update != updates.end(); ++update)
952 updated |= UpdateSetting(root, setting->second.setting, *update);
958 bool CSettingsManager::UpdateSetting(const TiXmlNode *node, CSetting *setting, const CSettingUpdate& update)
960 if (node == NULL || setting == NULL || update.GetType() == SettingUpdateTypeNone)
963 bool updated = false;
964 const char *oldSetting = NULL;
965 const TiXmlNode *oldSettingNode = NULL;
966 if (update.GetType() == SettingUpdateTypeRename)
968 if (update.GetValue().empty())
971 oldSetting = update.GetValue().c_str();
972 std::vector<std::string> parts = StringUtils::Split(oldSetting, ".");
973 if (parts.size() != 2 || parts.at(0).empty() || parts.at(1).empty())
976 const TiXmlNode *sectionNode = node->FirstChild(parts.at(0));
977 if (sectionNode == NULL)
980 oldSettingNode = sectionNode->FirstChild(parts.at(1));
981 if (oldSettingNode == NULL)
984 if (setting->FromString(oldSettingNode->FirstChild() != NULL ? oldSettingNode->FirstChild()->ValueStr() : StringUtils::Empty))
987 CLog::Log(LOGWARNING, "CSetting: unable to update \"%s\" through automatically renaming from \"%s\"", setting->GetId().c_str(), oldSetting);
990 updated |= OnSettingUpdate(setting, oldSetting, oldSettingNode);
994 void CSettingsManager::UpdateSettingByDependency(const std::string &settingId, const CSettingDependency &dependency)
996 CSetting *setting = GetSetting(settingId);
1000 switch (dependency.GetType())
1002 case SettingDependencyTypeEnable:
1003 // just trigger the property changed callback and a call to
1004 // CSetting::IsEnabled() will automatically determine the new
1006 OnSettingPropertyChanged(setting, "enabled");
1009 case SettingDependencyTypeUpdate:
1011 SettingType type = (SettingType)setting->GetType();
1012 if (type == SettingTypeInteger)
1014 CSettingInt *settingInt = ((CSettingInt*)setting);
1015 if (settingInt->GetOptionsType() == SettingOptionsTypeDynamic)
1016 settingInt->UpdateDynamicOptions();
1018 else if (type == SettingTypeString)
1020 CSettingString *settingString = ((CSettingString*)setting);
1021 if (settingString->GetOptionsType() == SettingOptionsTypeDynamic)
1022 settingString->UpdateDynamicOptions();
1027 case SettingDependencyTypeVisible:
1028 // just trigger the property changed callback and a call to
1029 // CSetting::IsVisible() will automatically determine the new
1031 OnSettingPropertyChanged(setting, "visible");
1034 case SettingDependencyTypeNone:
1040 void CSettingsManager::RegisterSettingOptionsFiller(const std::string &identifier, void *filler, SettingOptionsFillerType type)
1042 CExclusiveLock lock(m_critical);
1043 SettingOptionsFillerMap::const_iterator it = m_optionsFillers.find(identifier);
1044 if (it != m_optionsFillers.end())
1047 SettingOptionsFiller optionsFiller = { filler, type };
1048 m_optionsFillers.insert(make_pair(identifier, optionsFiller));