2 * Copyright (C) 2013-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 "SettingControl.h"
11 #include "settings/lib/SettingDefinitions.h"
12 #include "utils/StringUtils.h"
13 #include "utils/XBMCTinyXML.h"
14 #include "utils/XMLUtils.h"
15 #include "utils/log.h"
19 const char* SHOW_ADDONS_ALL
= "all";
20 const char* SHOW_ADDONS_INSTALLED
= "installed";
21 const char* SHOW_ADDONS_INSTALLABLE
= "installable";
23 std::shared_ptr
<ISettingControl
> CSettingControlCreator::CreateControl(const std::string
&controlType
) const
25 if (StringUtils::EqualsNoCase(controlType
, "toggle"))
26 return std::make_shared
<CSettingControlCheckmark
>();
27 else if (StringUtils::EqualsNoCase(controlType
, "spinner"))
28 return std::make_shared
<CSettingControlSpinner
>();
29 else if (StringUtils::EqualsNoCase(controlType
, "edit"))
30 return std::make_shared
<CSettingControlEdit
>();
31 else if (StringUtils::EqualsNoCase(controlType
, "button"))
32 return std::make_shared
<CSettingControlButton
>();
33 else if (StringUtils::EqualsNoCase(controlType
, "list"))
34 return std::make_shared
<CSettingControlList
>();
35 else if (StringUtils::EqualsNoCase(controlType
, "slider"))
36 return std::make_shared
<CSettingControlSlider
>();
37 else if (StringUtils::EqualsNoCase(controlType
, "range"))
38 return std::make_shared
<CSettingControlRange
>();
39 else if (StringUtils::EqualsNoCase(controlType
, "title"))
40 return std::make_shared
<CSettingControlTitle
>();
41 else if (StringUtils::EqualsNoCase(controlType
, "label"))
42 return std::make_shared
<CSettingControlLabel
>();
43 else if (StringUtils::EqualsNoCase(controlType
, "colorbutton"))
44 return std::make_shared
<CSettingControlColorButton
>();
49 bool CSettingControlCheckmark::SetFormat(const std::string
&format
)
51 return format
.empty() || StringUtils::EqualsNoCase(format
, "boolean");
54 bool CSettingControlFormattedRange::Deserialize(const TiXmlNode
*node
, bool update
/* = false */)
56 if (!ISettingControl::Deserialize(node
, update
))
59 if (m_format
== "string")
61 XMLUtils::GetInt(node
, SETTING_XML_ELM_CONTROL_FORMATLABEL
, m_formatLabel
);
63 // get the minimum label from <setting><constraints><minimum label="X" />
64 auto settingNode
= node
->Parent();
65 if (settingNode
!= nullptr)
67 auto constraintsNode
= settingNode
->FirstChild(SETTING_XML_ELM_CONSTRAINTS
);
68 if (constraintsNode
!= nullptr)
70 auto minimumNode
= constraintsNode
->FirstChild(SETTING_XML_ELM_MINIMUM
);
71 if (minimumNode
!= nullptr)
73 auto minimumElem
= minimumNode
->ToElement();
74 if (minimumElem
!= nullptr)
76 if (minimumElem
->QueryIntAttribute(SETTING_XML_ATTR_LABEL
, &m_minimumLabel
) != TIXML_SUCCESS
)
83 if (m_minimumLabel
< 0)
85 std::string strFormat
;
86 if (XMLUtils::GetString(node
, SETTING_XML_ATTR_FORMAT
, strFormat
) && !strFormat
.empty())
87 m_formatString
= strFormat
;
94 bool CSettingControlSpinner::SetFormat(const std::string
&format
)
96 if (!StringUtils::EqualsNoCase(format
, "string") &&
97 !StringUtils::EqualsNoCase(format
, "integer") &&
98 !StringUtils::EqualsNoCase(format
, "number"))
102 StringUtils::ToLower(m_format
);
107 bool CSettingControlEdit::Deserialize(const TiXmlNode
*node
, bool update
/* = false */)
109 if (!ISettingControl::Deserialize(node
, update
))
112 XMLUtils::GetBoolean(node
, SETTING_XML_ELM_CONTROL_HIDDEN
, m_hidden
);
113 XMLUtils::GetBoolean(node
, SETTING_XML_ELM_CONTROL_VERIFYNEW
, m_verifyNewValue
);
114 XMLUtils::GetInt(node
, SETTING_XML_ELM_CONTROL_HEADING
, m_heading
);
119 bool CSettingControlEdit::SetFormat(const std::string
&format
)
121 if (!StringUtils::EqualsNoCase(format
, "string") &&
122 !StringUtils::EqualsNoCase(format
, "integer") &&
123 !StringUtils::EqualsNoCase(format
, "number") &&
124 !StringUtils::EqualsNoCase(format
, "ip") &&
125 !StringUtils::EqualsNoCase(format
, "md5") &&
126 !StringUtils::EqualsNoCase(format
, "urlencoded"))
130 StringUtils::ToLower(m_format
);
135 bool CSettingControlButton::Deserialize(const TiXmlNode
*node
, bool update
/* = false */)
137 if (!ISettingControl::Deserialize(node
, update
))
140 XMLUtils::GetInt(node
, SETTING_XML_ELM_CONTROL_HEADING
, m_heading
);
141 XMLUtils::GetBoolean(node
, SETTING_XML_ELM_CONTROL_HIDEVALUE
, m_hideValue
);
143 if (m_format
== "action")
145 bool closeDialog
= false;
146 if (XMLUtils::GetBoolean(node
, "close", closeDialog
))
147 m_closeDialog
= closeDialog
;
148 std::string strActionData
;
149 if (XMLUtils::GetString(node
, SETTING_XML_ELM_DATA
, strActionData
))
150 m_actionData
= strActionData
;
152 else if (m_format
== "addon")
154 std::string strShowAddons
;
155 if (XMLUtils::GetString(node
, "show", strShowAddons
) && !strShowAddons
.empty())
157 if (StringUtils::EqualsNoCase(strShowAddons
, SHOW_ADDONS_ALL
))
159 m_showInstalledAddons
= true;
160 m_showInstallableAddons
= true;
162 else if (StringUtils::EqualsNoCase(strShowAddons
, SHOW_ADDONS_INSTALLED
))
164 m_showInstalledAddons
= true;
165 m_showInstallableAddons
= false;
167 else if (StringUtils::EqualsNoCase(strShowAddons
, SHOW_ADDONS_INSTALLABLE
))
169 m_showInstalledAddons
= false;
170 m_showInstallableAddons
= true;
173 CLog::Log(LOGWARNING
, "CSettingControlButton: invalid <show>");
175 auto show
= node
->FirstChildElement("show");
178 const char *strShowDetails
= nullptr;
179 if ((strShowDetails
= show
->Attribute(SETTING_XML_ATTR_SHOW_DETAILS
)) != nullptr)
181 if (StringUtils::EqualsNoCase(strShowDetails
, "false") || StringUtils::EqualsNoCase(strShowDetails
, "true"))
182 m_showAddonDetails
= StringUtils::EqualsNoCase(strShowDetails
, "true");
184 CLog::Log(LOGWARNING
, "CSettingControlButton: error reading \"details\" attribute of <show>");
187 if (!m_showInstallableAddons
)
189 const char *strShowMore
= nullptr;
190 if ((strShowMore
= show
->Attribute(SETTING_XML_ATTR_SHOW_MORE
)) != nullptr)
192 if (StringUtils::EqualsNoCase(strShowMore
, "false") || StringUtils::EqualsNoCase(strShowMore
, "true"))
193 m_showMoreAddons
= StringUtils::EqualsNoCase(strShowMore
, "true");
195 CLog::Log(LOGWARNING
, "CSettingControlButton: error reading \"more\" attribute of <show>");
201 else if (m_format
== "file")
203 bool useThumbs
= false;
204 if (XMLUtils::GetBoolean(node
, "usethumbs", useThumbs
))
205 m_useImageThumbs
= useThumbs
;
206 bool useFileDirectories
= false;
207 if (XMLUtils::GetBoolean(node
, "treatasfolder", useFileDirectories
))
208 m_useFileDirectories
= useFileDirectories
;
214 bool CSettingControlButton::SetFormat(const std::string
&format
)
216 if (!StringUtils::EqualsNoCase(format
, "path") &&
217 !StringUtils::EqualsNoCase(format
, "file") &&
218 !StringUtils::EqualsNoCase(format
, "image") &&
219 !StringUtils::EqualsNoCase(format
, "addon") &&
220 !StringUtils::EqualsNoCase(format
, "action") &&
221 !StringUtils::EqualsNoCase(format
, "infolabel") &&
222 !StringUtils::EqualsNoCase(format
, "date") &&
223 !StringUtils::EqualsNoCase(format
, "time"))
227 StringUtils::ToLower(m_format
);
232 bool CSettingControlList::Deserialize(const TiXmlNode
*node
, bool update
/* = false */)
234 if (!CSettingControlFormattedRange::Deserialize(node
, update
))
237 XMLUtils::GetInt(node
, SETTING_XML_ELM_CONTROL_HEADING
, m_heading
);
238 XMLUtils::GetBoolean(node
, SETTING_XML_ELM_CONTROL_MULTISELECT
, m_multiselect
);
239 XMLUtils::GetBoolean(node
, SETTING_XML_ELM_CONTROL_HIDEVALUE
, m_hideValue
);
240 XMLUtils::GetInt(node
, SETTING_XML_ELM_CONTROL_ADDBUTTONLABEL
, m_addButtonLabel
);
245 bool CSettingControlList::SetFormat(const std::string
&format
)
247 if (!StringUtils::EqualsNoCase(format
, "string") &&
248 !StringUtils::EqualsNoCase(format
, "integer"))
252 StringUtils::ToLower(m_format
);
257 bool CSettingControlSlider::Deserialize(const TiXmlNode
*node
, bool update
/* = false */)
259 if (!ISettingControl::Deserialize(node
, update
))
262 XMLUtils::GetInt(node
, SETTING_XML_ELM_CONTROL_HEADING
, m_heading
);
263 XMLUtils::GetBoolean(node
, SETTING_XML_ELM_CONTROL_POPUP
, m_popup
);
265 XMLUtils::GetInt(node
, SETTING_XML_ELM_CONTROL_FORMATLABEL
, m_formatLabel
);
266 if (m_formatLabel
< 0)
268 std::string strFormat
;
269 if (XMLUtils::GetString(node
, SETTING_XML_ATTR_FORMAT
, strFormat
) && !strFormat
.empty())
270 m_formatString
= strFormat
;
276 bool CSettingControlSlider::SetFormat(const std::string
&format
)
278 if (!StringUtils::EqualsNoCase(format
, "percentage") &&
279 !StringUtils::EqualsNoCase(format
, "integer") &&
280 !StringUtils::EqualsNoCase(format
, "number"))
284 StringUtils::ToLower(m_format
);
285 m_formatString
= GetDefaultFormatString();
290 std::string
CSettingControlSlider::GetDefaultFormatString() const
292 if (m_format
== "percentage")
294 if (m_format
== "integer")
296 if (m_format
== "number")
302 bool CSettingControlRange::Deserialize(const TiXmlNode
*node
, bool update
/* = false */)
304 if (!ISettingControl::Deserialize(node
, update
))
307 auto formatLabel
= node
->FirstChildElement(SETTING_XML_ELM_CONTROL_FORMATLABEL
);
308 if (formatLabel
!= nullptr)
310 XMLUtils::GetInt(node
, SETTING_XML_ELM_CONTROL_FORMATLABEL
, m_formatLabel
);
311 if (m_formatLabel
< 0)
314 auto formatValue
= formatLabel
->Attribute(SETTING_XML_ELM_CONTROL_FORMATVALUE
);
315 if (formatValue
!= nullptr)
317 if (StringUtils::IsInteger(formatValue
))
318 m_valueFormatLabel
= (int)strtol(formatValue
, nullptr, 0);
321 m_valueFormat
= formatValue
;
322 if (!m_valueFormat
.empty())
323 m_valueFormatLabel
= -1;
331 bool CSettingControlRange::SetFormat(const std::string
&format
)
333 if (StringUtils::EqualsNoCase(format
, "percentage"))
334 m_valueFormat
= "{} %";
335 else if (StringUtils::EqualsNoCase(format
, "integer"))
336 m_valueFormat
= "{:d}";
337 else if (StringUtils::EqualsNoCase(format
, "number"))
338 m_valueFormat
= "{:.1f}";
339 else if (StringUtils::EqualsNoCase(format
, "date") ||
340 StringUtils::EqualsNoCase(format
, "time"))
341 m_valueFormat
.clear();
346 StringUtils::ToLower(m_format
);
351 bool CSettingControlTitle::Deserialize(const TiXmlNode
*node
, bool update
/* = false */)
353 if (!ISettingControl::Deserialize(node
, update
))
357 if (XMLUtils::GetString(node
, SETTING_XML_ATTR_SEPARATOR_POSITION
, strTmp
))
359 if (!StringUtils::EqualsNoCase(strTmp
, "top") && !StringUtils::EqualsNoCase(strTmp
, "bottom"))
360 CLog::Log(LOGWARNING
, "CSettingControlTitle: error reading \"value\" attribute of <{}>",
361 SETTING_XML_ATTR_SEPARATOR_POSITION
);
363 m_separatorBelowLabel
= StringUtils::EqualsNoCase(strTmp
, "bottom");
365 XMLUtils::GetBoolean(node
, SETTING_XML_ATTR_HIDE_SEPARATOR
, m_separatorHidden
);
370 CSettingControlLabel::CSettingControlLabel()
375 bool CSettingControlColorButton::SetFormat(const std::string
& format
)
377 return format
.empty() || StringUtils::EqualsNoCase(format
, "string");