diff options
Diffstat (limited to 'xbmc/addons/GUIDialogAddonSettings.cpp')
| -rw-r--r-- | xbmc/addons/GUIDialogAddonSettings.cpp | 1200 |
1 files changed, 1200 insertions, 0 deletions
diff --git a/xbmc/addons/GUIDialogAddonSettings.cpp b/xbmc/addons/GUIDialogAddonSettings.cpp new file mode 100644 index 0000000..ef1c3c2 --- /dev/null +++ b/xbmc/addons/GUIDialogAddonSettings.cpp | |||
| @@ -0,0 +1,1200 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005-2013 Team XBMC | ||
| 3 | * http://xbmc.org | ||
| 4 | * | ||
| 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) | ||
| 8 | * any later version. | ||
| 9 | * | ||
| 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. | ||
| 14 | * | ||
| 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/>. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include "GUIDialogAddonSettings.h" | ||
| 22 | #include "filesystem/PluginDirectory.h" | ||
| 23 | #include "addons/IAddon.h" | ||
| 24 | #include "addons/AddonManager.h" | ||
| 25 | #include "dialogs/GUIDialogNumeric.h" | ||
| 26 | #include "dialogs/GUIDialogFileBrowser.h" | ||
| 27 | #include "dialogs/GUIDialogOK.h" | ||
| 28 | #include "guilib/GUIControlGroupList.h" | ||
| 29 | #include "guilib/GUISettingsSliderControl.h" | ||
| 30 | #include "utils/URIUtils.h" | ||
| 31 | #include "utils/StringUtils.h" | ||
| 32 | #include "storage/MediaManager.h" | ||
| 33 | #include "guilib/GUILabelControl.h" | ||
| 34 | #include "guilib/GUIRadioButtonControl.h" | ||
| 35 | #include "guilib/GUISpinControlEx.h" | ||
| 36 | #include "guilib/GUIImage.h" | ||
| 37 | #include "input/Key.h" | ||
| 38 | #include "filesystem/Directory.h" | ||
| 39 | #include "video/VideoInfoScanner.h" | ||
| 40 | #include "addons/Scraper.h" | ||
| 41 | #include "guilib/GUIWindowManager.h" | ||
| 42 | #include "ApplicationMessenger.h" | ||
| 43 | #include "guilib/GUIKeyboardFactory.h" | ||
| 44 | #include "FileItem.h" | ||
| 45 | #include "settings/AdvancedSettings.h" | ||
| 46 | #include "settings/MediaSourceSettings.h" | ||
| 47 | #include "GUIInfoManager.h" | ||
| 48 | #include "GUIUserMessages.h" | ||
| 49 | #include "dialogs/GUIDialogSelect.h" | ||
| 50 | #include "GUIWindowAddonBrowser.h" | ||
| 51 | #include "utils/log.h" | ||
| 52 | #include "Util.h" | ||
| 53 | #include "URL.h" | ||
| 54 | #include "utils/XMLUtils.h" | ||
| 55 | |||
| 56 | using namespace std; | ||
| 57 | using namespace ADDON; | ||
| 58 | using XFILE::CDirectory; | ||
| 59 | |||
| 60 | #define CONTROL_SETTINGS_AREA 2 | ||
| 61 | #define CONTROL_DEFAULT_BUTTON 3 | ||
| 62 | #define CONTROL_DEFAULT_RADIOBUTTON 4 | ||
| 63 | #define CONTROL_DEFAULT_SPIN 5 | ||
| 64 | #define CONTROL_DEFAULT_SEPARATOR 6 | ||
| 65 | #define CONTROL_DEFAULT_LABEL_SEPARATOR 7 | ||
| 66 | #define CONTROL_DEFAULT_SLIDER 8 | ||
| 67 | #define CONTROL_SECTION_AREA 9 | ||
| 68 | #define CONTROL_DEFAULT_SECTION_BUTTON 13 | ||
| 69 | |||
| 70 | #define ID_BUTTON_OK 10 | ||
| 71 | #define ID_BUTTON_CANCEL 11 | ||
| 72 | #define ID_BUTTON_DEFAULT 12 | ||
| 73 | #define CONTROL_HEADING_LABEL 20 | ||
| 74 | |||
| 75 | #define CONTROL_START_SECTION 100 | ||
| 76 | #define CONTROL_START_SETTING 200 | ||
| 77 | |||
| 78 | CGUIDialogAddonSettings::CGUIDialogAddonSettings() | ||
| 79 | : CGUIDialogBoxBase(WINDOW_DIALOG_ADDON_SETTINGS, "DialogAddonSettings.xml") | ||
| 80 | { | ||
| 81 | m_currentSection = 0; | ||
| 82 | m_totalSections = 1; | ||
| 83 | m_saveToDisk = false; | ||
| 84 | } | ||
| 85 | |||
| 86 | CGUIDialogAddonSettings::~CGUIDialogAddonSettings(void) | ||
| 87 | { | ||
| 88 | } | ||
| 89 | |||
| 90 | bool CGUIDialogAddonSettings::OnMessage(CGUIMessage& message) | ||
| 91 | { | ||
| 92 | switch (message.GetMessage()) | ||
| 93 | { | ||
| 94 | case GUI_MSG_WINDOW_DEINIT: | ||
| 95 | { | ||
| 96 | FreeSections(); | ||
| 97 | } | ||
| 98 | break; | ||
| 99 | case GUI_MSG_CLICKED: | ||
| 100 | { | ||
| 101 | int iControl = message.GetSenderId(); | ||
| 102 | bool bCloseDialog = false; | ||
| 103 | |||
| 104 | if (iControl == ID_BUTTON_DEFAULT) | ||
| 105 | SetDefaultSettings(); | ||
| 106 | else if (iControl != ID_BUTTON_OK) | ||
| 107 | bCloseDialog = ShowVirtualKeyboard(iControl); | ||
| 108 | |||
| 109 | if (iControl == ID_BUTTON_OK || iControl == ID_BUTTON_CANCEL || bCloseDialog) | ||
| 110 | { | ||
| 111 | if (iControl == ID_BUTTON_OK || bCloseDialog) | ||
| 112 | { | ||
| 113 | m_bConfirmed = true; | ||
| 114 | SaveSettings(); | ||
| 115 | } | ||
| 116 | Close(); | ||
| 117 | return true; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | break; | ||
| 121 | case GUI_MSG_FOCUSED: | ||
| 122 | { | ||
| 123 | CGUIDialogBoxBase::OnMessage(message); | ||
| 124 | int focusedControl = GetFocusedControlID(); | ||
| 125 | if (focusedControl >= CONTROL_START_SECTION && focusedControl < (int)(CONTROL_START_SECTION + m_totalSections) && | ||
| 126 | focusedControl - CONTROL_START_SECTION != (int)m_currentSection) | ||
| 127 | { // changing section | ||
| 128 | UpdateFromControls(); | ||
| 129 | m_currentSection = focusedControl - CONTROL_START_SECTION; | ||
| 130 | CreateControls(); | ||
| 131 | } | ||
| 132 | return true; | ||
| 133 | } | ||
| 134 | case GUI_MSG_SETTING_UPDATED: | ||
| 135 | { | ||
| 136 | std::string id = message.GetStringParam(0); | ||
| 137 | std::string value = message.GetStringParam(1); | ||
| 138 | m_settings[id] = value; | ||
| 139 | if (GetFocusedControl()) | ||
| 140 | { | ||
| 141 | int iControl = GetFocusedControl()->GetID(); | ||
| 142 | CreateControls(); | ||
| 143 | CGUIMessage msg(GUI_MSG_SETFOCUS,GetID(),iControl); | ||
| 144 | OnMessage(msg); | ||
| 145 | } | ||
| 146 | return true; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | return CGUIDialogBoxBase::OnMessage(message); | ||
| 150 | } | ||
| 151 | |||
| 152 | bool CGUIDialogAddonSettings::OnAction(const CAction& action) | ||
| 153 | { | ||
| 154 | if (action.GetID() == ACTION_DELETE_ITEM) | ||
| 155 | { | ||
| 156 | CGUIControl* pControl = GetFocusedControl(); | ||
| 157 | if (pControl) | ||
| 158 | { | ||
| 159 | int iControl = pControl->GetID(); | ||
| 160 | int controlId = CONTROL_START_SETTING; | ||
| 161 | const TiXmlElement* setting = GetFirstSetting(); | ||
| 162 | UpdateFromControls(); | ||
| 163 | while (setting) | ||
| 164 | { | ||
| 165 | if (controlId == iControl) | ||
| 166 | { | ||
| 167 | const char* id = setting->Attribute("id"); | ||
| 168 | const char* value = setting->Attribute("default"); | ||
| 169 | if (id && value) | ||
| 170 | m_settings[id] = value; | ||
| 171 | CreateControls(); | ||
| 172 | CGUIMessage msg(GUI_MSG_SETFOCUS,GetID(),iControl); | ||
| 173 | OnMessage(msg); | ||
| 174 | return true; | ||
| 175 | } | ||
| 176 | setting = setting->NextSiblingElement("setting"); | ||
| 177 | controlId++; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| 181 | return CGUIDialogBoxBase::OnAction(action); | ||
| 182 | } | ||
| 183 | |||
| 184 | void CGUIDialogAddonSettings::OnInitWindow() | ||
| 185 | { | ||
| 186 | m_currentSection = 0; | ||
| 187 | m_totalSections = 1; | ||
| 188 | CreateSections(); | ||
| 189 | CreateControls(); | ||
| 190 | CGUIDialogBoxBase::OnInitWindow(); | ||
| 191 | } | ||
| 192 | |||
| 193 | // \brief Show CGUIDialogOK dialog, then wait for user to dismiss it. | ||
| 194 | bool CGUIDialogAddonSettings::ShowAndGetInput(const AddonPtr &addon, bool saveToDisk /* = true */) | ||
| 195 | { | ||
| 196 | if (!addon) | ||
| 197 | return false; | ||
| 198 | |||
| 199 | if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER)) | ||
| 200 | return false; | ||
| 201 | |||
| 202 | bool ret(false); | ||
| 203 | if (addon->HasSettings()) | ||
| 204 | { | ||
| 205 | // Create the dialog | ||
| 206 | CGUIDialogAddonSettings* pDialog = NULL; | ||
| 207 | pDialog = (CGUIDialogAddonSettings*) g_windowManager.GetWindow(WINDOW_DIALOG_ADDON_SETTINGS); | ||
| 208 | if (!pDialog) | ||
| 209 | return false; | ||
| 210 | |||
| 211 | // Set the heading | ||
| 212 | std::string heading = StringUtils::Format("$LOCALIZE[10004] - %s", addon->Name().c_str()); // "Settings - AddonName" | ||
| 213 | pDialog->m_strHeading = heading; | ||
| 214 | |||
| 215 | pDialog->m_addon = addon; | ||
| 216 | pDialog->m_saveToDisk = saveToDisk; | ||
| 217 | pDialog->DoModal(); | ||
| 218 | ret = true; | ||
| 219 | } | ||
| 220 | else | ||
| 221 | { // addon does not support settings, inform user | ||
| 222 | CGUIDialogOK::ShowAndGetInput(24000,0,24030,0); | ||
| 223 | } | ||
| 224 | |||
| 225 | return ret; | ||
| 226 | } | ||
| 227 | |||
| 228 | bool CGUIDialogAddonSettings::ShowVirtualKeyboard(int iControl) | ||
| 229 | { | ||
| 230 | int controlId = CONTROL_START_SETTING; | ||
| 231 | bool bCloseDialog = false; | ||
| 232 | |||
| 233 | const TiXmlElement *setting = GetFirstSetting(); | ||
| 234 | while (setting) | ||
| 235 | { | ||
| 236 | if (controlId == iControl) | ||
| 237 | { | ||
| 238 | const CGUIControl* control = GetControl(controlId); | ||
| 239 | const std::string id = XMLUtils::GetAttribute(setting, "id"); | ||
| 240 | const std::string type = XMLUtils::GetAttribute(setting, "type"); | ||
| 241 | |||
| 242 | //Special handling for actions: does not require id attribute. TODO: refactor me. | ||
| 243 | if (control && control->GetControlType() == CGUIControl::GUICONTROL_BUTTON && type == "action") | ||
| 244 | { | ||
| 245 | const char *option = setting->Attribute("option"); | ||
| 246 | std::string action = XMLUtils::GetAttribute(setting, "action"); | ||
| 247 | if (!action.empty()) | ||
| 248 | { | ||
| 249 | // replace $CWD with the url of plugin/script | ||
| 250 | StringUtils::Replace(action, "$CWD", m_addon->Path()); | ||
| 251 | StringUtils::Replace(action, "$ID", m_addon->ID()); | ||
| 252 | if (option) | ||
| 253 | bCloseDialog = (strcmpi(option, "close") == 0); | ||
| 254 | CApplicationMessenger::Get().ExecBuiltIn(action); | ||
| 255 | } | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | |||
| 259 | if (control && control->GetControlType() == CGUIControl::GUICONTROL_BUTTON && | ||
| 260 | !id.empty() && !type.empty()) | ||
| 261 | { | ||
| 262 | const char *option = setting->Attribute("option"); | ||
| 263 | const char *source = setting->Attribute("source"); | ||
| 264 | std::string value = m_buttonValues[id]; | ||
| 265 | std::string label = GetString(setting->Attribute("label")); | ||
| 266 | |||
| 267 | if (type == "text") | ||
| 268 | { | ||
| 269 | // get any options | ||
| 270 | bool bHidden = false; | ||
| 271 | bool bEncoded = false; | ||
| 272 | if (option) | ||
| 273 | { | ||
| 274 | bHidden = (strstr(option, "hidden") != NULL); | ||
| 275 | bEncoded = (strstr(option, "urlencoded") != NULL); | ||
| 276 | } | ||
| 277 | if (bEncoded) | ||
| 278 | value = CURL::Decode(value); | ||
| 279 | |||
| 280 | if (CGUIKeyboardFactory::ShowAndGetInput(value, label, true, bHidden)) | ||
| 281 | { | ||
| 282 | // if hidden hide input | ||
| 283 | if (bHidden) | ||
| 284 | { | ||
| 285 | std::string hiddenText; | ||
| 286 | hiddenText.append(value.size(), L'*'); | ||
| 287 | ((CGUIButtonControl *)control)->SetLabel2(hiddenText); | ||
| 288 | } | ||
| 289 | else | ||
| 290 | ((CGUIButtonControl*) control)->SetLabel2(value); | ||
| 291 | if (bEncoded) | ||
| 292 | value = CURL::Encode(value); | ||
| 293 | } | ||
| 294 | } | ||
| 295 | else if (type == "number" && CGUIDialogNumeric::ShowAndGetNumber(value, label)) | ||
| 296 | { | ||
| 297 | ((CGUIButtonControl*) control)->SetLabel2(value); | ||
| 298 | } | ||
| 299 | else if (type == "ipaddress" && CGUIDialogNumeric::ShowAndGetIPAddress(value, label)) | ||
| 300 | { | ||
| 301 | ((CGUIButtonControl*) control)->SetLabel2(value); | ||
| 302 | } | ||
| 303 | else if (type == "select") | ||
| 304 | { | ||
| 305 | CGUIDialogSelect *pDlg = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); | ||
| 306 | if (pDlg) | ||
| 307 | { | ||
| 308 | pDlg->SetHeading(label.c_str()); | ||
| 309 | pDlg->Reset(); | ||
| 310 | |||
| 311 | int selected = -1; | ||
| 312 | vector<std::string> valuesVec; | ||
| 313 | if (setting->Attribute("values")) | ||
| 314 | StringUtils::Tokenize(setting->Attribute("values"), valuesVec, "|"); | ||
| 315 | else if (setting->Attribute("lvalues")) | ||
| 316 | { // localize | ||
| 317 | StringUtils::Tokenize(setting->Attribute("lvalues"), valuesVec, "|"); | ||
| 318 | for (unsigned int i = 0; i < valuesVec.size(); i++) | ||
| 319 | { | ||
| 320 | if (i == (unsigned int)atoi(value.c_str())) | ||
| 321 | selected = i; | ||
| 322 | std::string localized = m_addon->GetString(atoi(valuesVec[i].c_str())); | ||
| 323 | if (localized.empty()) | ||
| 324 | localized = g_localizeStrings.Get(atoi(valuesVec[i].c_str())); | ||
| 325 | valuesVec[i] = localized; | ||
| 326 | } | ||
| 327 | } | ||
| 328 | else if (source) | ||
| 329 | { | ||
| 330 | valuesVec = GetFileEnumValues(source, XMLUtils::GetAttribute(setting, "mask"), XMLUtils::GetAttribute(setting, "option")); | ||
| 331 | } | ||
| 332 | |||
| 333 | for (unsigned int i = 0; i < valuesVec.size(); i++) | ||
| 334 | { | ||
| 335 | pDlg->Add(valuesVec[i]); | ||
| 336 | if (selected == (int)i || (selected < 0 && StringUtils::EqualsNoCase(valuesVec[i], value))) | ||
| 337 | pDlg->SetSelected(i); // FIXME: the SetSelected() does not select "i", it always defaults to the first position | ||
| 338 | } | ||
| 339 | pDlg->DoModal(); | ||
| 340 | int iSelected = pDlg->GetSelectedLabel(); | ||
| 341 | if (iSelected >= 0) | ||
| 342 | { | ||
| 343 | if (setting->Attribute("lvalues")) | ||
| 344 | value = StringUtils::Format("%i", iSelected); | ||
| 345 | else | ||
| 346 | value = valuesVec[iSelected]; | ||
| 347 | ((CGUIButtonControl*) control)->SetLabel2(valuesVec[iSelected]); | ||
| 348 | } | ||
| 349 | } | ||
| 350 | } | ||
| 351 | else if (type == "audio" || type == "video" | ||
| 352 | || type == "image" || type == "executable" | ||
| 353 | || type == "file" || type == "folder") | ||
| 354 | { | ||
| 355 | // setup the shares | ||
| 356 | VECSOURCES *shares = NULL; | ||
| 357 | if (source && strcmpi(source, "") != 0) | ||
| 358 | shares = CMediaSourceSettings::Get().GetSources(source); | ||
| 359 | |||
| 360 | VECSOURCES localShares; | ||
| 361 | if (!shares) | ||
| 362 | { | ||
| 363 | g_mediaManager.GetLocalDrives(localShares); | ||
| 364 | if (!source || strcmpi(source, "local") != 0) | ||
| 365 | g_mediaManager.GetNetworkLocations(localShares); | ||
| 366 | } | ||
| 367 | else // always append local drives | ||
| 368 | { | ||
| 369 | localShares = *shares; | ||
| 370 | g_mediaManager.GetLocalDrives(localShares); | ||
| 371 | } | ||
| 372 | |||
| 373 | if (type == "folder") | ||
| 374 | { | ||
| 375 | // get any options | ||
| 376 | bool bWriteOnly = false; | ||
| 377 | if (option) | ||
| 378 | bWriteOnly = (strcmpi(option, "writeable") == 0); | ||
| 379 | |||
| 380 | if (CGUIDialogFileBrowser::ShowAndGetDirectory(localShares, label, value, bWriteOnly)) | ||
| 381 | ((CGUIButtonControl*) control)->SetLabel2(value); | ||
| 382 | } | ||
| 383 | else if (type == "image") | ||
| 384 | { | ||
| 385 | if (CGUIDialogFileBrowser::ShowAndGetImage(localShares, label, value)) | ||
| 386 | ((CGUIButtonControl*) control)->SetLabel2(value); | ||
| 387 | } | ||
| 388 | else | ||
| 389 | { | ||
| 390 | // set the proper mask | ||
| 391 | std::string strMask; | ||
| 392 | if (setting->Attribute("mask")) | ||
| 393 | { | ||
| 394 | strMask = setting->Attribute("mask"); | ||
| 395 | // convert mask qualifiers | ||
| 396 | StringUtils::Replace(strMask, "$AUDIO", g_advancedSettings.m_musicExtensions); | ||
| 397 | StringUtils::Replace(strMask, "$VIDEO", g_advancedSettings.m_videoExtensions); | ||
| 398 | StringUtils::Replace(strMask, "$IMAGE", g_advancedSettings.m_pictureExtensions); | ||
| 399 | #if defined(_WIN32_WINNT) | ||
| 400 | StringUtils::Replace(strMask, "$EXECUTABLE", ".exe|.bat|.cmd|.py"); | ||
| 401 | #else | ||
| 402 | StringUtils::Replace(strMask, "$EXECUTABLE", ""); | ||
| 403 | #endif | ||
| 404 | } | ||
| 405 | else | ||
| 406 | { | ||
| 407 | if (type == "video") | ||
| 408 | strMask = g_advancedSettings.m_videoExtensions; | ||
| 409 | else if (type == "audio") | ||
| 410 | strMask = g_advancedSettings.m_musicExtensions; | ||
| 411 | else if (type == "executable") | ||
| 412 | #if defined(_WIN32_WINNT) | ||
| 413 | strMask = ".exe|.bat|.cmd|.py"; | ||
| 414 | #else | ||
| 415 | strMask = ""; | ||
| 416 | #endif | ||
| 417 | } | ||
| 418 | |||
| 419 | // get any options | ||
| 420 | bool bUseThumbs = false; | ||
| 421 | bool bUseFileDirectories = false; | ||
| 422 | if (option) | ||
| 423 | { | ||
| 424 | vector<string> options = StringUtils::Split(option, '|'); | ||
| 425 | bUseThumbs = find(options.begin(), options.end(), "usethumbs") != options.end(); | ||
| 426 | bUseFileDirectories = find(options.begin(), options.end(), "treatasfolder") != options.end(); | ||
| 427 | } | ||
| 428 | |||
| 429 | if (CGUIDialogFileBrowser::ShowAndGetFile(localShares, strMask, label, value, bUseThumbs, bUseFileDirectories)) | ||
| 430 | ((CGUIButtonControl*) control)->SetLabel2(value); | ||
| 431 | } | ||
| 432 | } | ||
| 433 | else if (type == "date") | ||
| 434 | { | ||
| 435 | CDateTime date; | ||
| 436 | if (!value.empty()) | ||
| 437 | date.SetFromDBDate(value); | ||
| 438 | SYSTEMTIME timedate; | ||
| 439 | date.GetAsSystemTime(timedate); | ||
| 440 | if(CGUIDialogNumeric::ShowAndGetDate(timedate, label)) | ||
| 441 | { | ||
| 442 | date = timedate; | ||
| 443 | value = date.GetAsDBDate(); | ||
| 444 | ((CGUIButtonControl*) control)->SetLabel2(value); | ||
| 445 | } | ||
| 446 | } | ||
| 447 | else if (type == "time") | ||
| 448 | { | ||
| 449 | SYSTEMTIME timedate; | ||
| 450 | if (value.size() >= 5) | ||
| 451 | { | ||
| 452 | // assumes HH:MM | ||
| 453 | timedate.wHour = atoi(value.substr(0, 2).c_str()); | ||
| 454 | timedate.wMinute = atoi(value.substr(3, 2).c_str()); | ||
| 455 | } | ||
| 456 | if (CGUIDialogNumeric::ShowAndGetTime(timedate, label)) | ||
| 457 | { | ||
| 458 | value = StringUtils::Format("%02d:%02d", timedate.wHour, timedate.wMinute); | ||
| 459 | ((CGUIButtonControl*) control)->SetLabel2(value); | ||
| 460 | } | ||
| 461 | } | ||
| 462 | else if (type == "addon") | ||
| 463 | { | ||
| 464 | const char *strType = setting->Attribute("addontype"); | ||
| 465 | if (strType) | ||
| 466 | { | ||
| 467 | vector<string> addonTypes = StringUtils::Split(strType, ','); | ||
| 468 | vector<ADDON::TYPE> types; | ||
| 469 | for (vector<string>::iterator i = addonTypes.begin(); i != addonTypes.end(); ++i) | ||
| 470 | { | ||
| 471 | StringUtils::Trim(*i); | ||
| 472 | ADDON::TYPE type = TranslateType(*i); | ||
| 473 | if (type != ADDON_UNKNOWN) | ||
| 474 | types.push_back(type); | ||
| 475 | } | ||
| 476 | if (types.size() > 0) | ||
| 477 | { | ||
| 478 | const char *strMultiselect = setting->Attribute("multiselect"); | ||
| 479 | bool multiSelect = strMultiselect && strcmpi(strMultiselect, "true") == 0; | ||
| 480 | if (multiSelect) | ||
| 481 | { | ||
| 482 | // construct vector of addon IDs (IDs are comma seperated in single string) | ||
| 483 | vector<string> addonIDs = StringUtils::Split(value, ','); | ||
| 484 | if (CGUIWindowAddonBrowser::SelectAddonID(types, addonIDs, false) == 1) | ||
| 485 | { | ||
| 486 | value = StringUtils::Join(addonIDs, ","); | ||
| 487 | ((CGUIButtonControl*) control)->SetLabel2(GetAddonNames(value)); | ||
| 488 | } | ||
| 489 | } | ||
| 490 | else // no need of string splitting/joining if we select only 1 addon | ||
| 491 | if (CGUIWindowAddonBrowser::SelectAddonID(types, value, false) == 1) | ||
| 492 | ((CGUIButtonControl*) control)->SetLabel2(GetAddonNames(value)); | ||
| 493 | } | ||
| 494 | } | ||
| 495 | } | ||
| 496 | m_buttonValues[id] = value; | ||
| 497 | break; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | setting = setting->NextSiblingElement("setting"); | ||
| 501 | controlId++; | ||
| 502 | } | ||
| 503 | EnableControls(); | ||
| 504 | return bCloseDialog; | ||
| 505 | } | ||
| 506 | |||
| 507 | void CGUIDialogAddonSettings::UpdateFromControls() | ||
| 508 | { | ||
| 509 | int controlID = CONTROL_START_SETTING; | ||
| 510 | const TiXmlElement *setting = GetFirstSetting(); | ||
| 511 | while (setting) | ||
| 512 | { | ||
| 513 | const std::string id = XMLUtils::GetAttribute(setting, "id"); | ||
| 514 | const std::string type = XMLUtils::GetAttribute(setting, "type"); | ||
| 515 | const CGUIControl* control = GetControl(controlID++); | ||
| 516 | |||
| 517 | if (control) | ||
| 518 | { | ||
| 519 | std::string value; | ||
| 520 | switch (control->GetControlType()) | ||
| 521 | { | ||
| 522 | case CGUIControl::GUICONTROL_BUTTON: | ||
| 523 | value = m_buttonValues[id]; | ||
| 524 | break; | ||
| 525 | case CGUIControl::GUICONTROL_RADIO: | ||
| 526 | value = ((CGUIRadioButtonControl*) control)->IsSelected() ? "true" : "false"; | ||
| 527 | break; | ||
| 528 | case CGUIControl::GUICONTROL_SPINEX: | ||
| 529 | if (type == "fileenum" || type == "labelenum") | ||
| 530 | value = ((CGUISpinControlEx*) control)->GetLabel(); | ||
| 531 | else | ||
| 532 | value = StringUtils::Format("%i", ((CGUISpinControlEx*) control)->GetValue()); | ||
| 533 | break; | ||
| 534 | case CGUIControl::GUICONTROL_SETTINGS_SLIDER: | ||
| 535 | { | ||
| 536 | std::string option = XMLUtils::GetAttribute(setting, "option"); | ||
| 537 | if (option.size() == 0 || StringUtils::EqualsNoCase(option, "float")) | ||
| 538 | value = StringUtils::Format("%f", ((CGUISettingsSliderControl *)control)->GetFloatValue()); | ||
| 539 | else | ||
| 540 | value = StringUtils::Format("%i", ((CGUISettingsSliderControl *)control)->GetIntValue()); | ||
| 541 | } | ||
| 542 | break; | ||
| 543 | default: | ||
| 544 | break; | ||
| 545 | } | ||
| 546 | m_settings[id] = value; | ||
| 547 | } | ||
| 548 | |||
| 549 | setting = setting->NextSiblingElement("setting"); | ||
| 550 | } | ||
| 551 | } | ||
| 552 | |||
| 553 | void CGUIDialogAddonSettings::SaveSettings(void) | ||
| 554 | { | ||
| 555 | UpdateFromControls(); | ||
| 556 | |||
| 557 | for (map<std::string, std::string>::iterator i = m_settings.begin(); i != m_settings.end(); ++i) | ||
| 558 | m_addon->UpdateSetting(i->first, i->second); | ||
| 559 | |||
| 560 | if (m_saveToDisk) | ||
| 561 | { | ||
| 562 | m_addon->SaveSettings(); | ||
| 563 | } | ||
| 564 | } | ||
| 565 | |||
| 566 | void CGUIDialogAddonSettings::FreeSections() | ||
| 567 | { | ||
| 568 | CGUIControlGroupList *group = dynamic_cast<CGUIControlGroupList *>(GetControl(CONTROL_SECTION_AREA)); | ||
| 569 | if (group) | ||
| 570 | { | ||
| 571 | group->FreeResources(); | ||
| 572 | group->ClearAll(); | ||
| 573 | } | ||
| 574 | m_settings.clear(); | ||
| 575 | m_buttonValues.clear(); | ||
| 576 | FreeControls(); | ||
| 577 | } | ||
| 578 | |||
| 579 | void CGUIDialogAddonSettings::FreeControls() | ||
| 580 | { | ||
| 581 | // clear the category group | ||
| 582 | CGUIControlGroupList *control = dynamic_cast<CGUIControlGroupList *>(GetControl(CONTROL_SETTINGS_AREA)); | ||
| 583 | if (control) | ||
| 584 | { | ||
| 585 | control->FreeResources(); | ||
| 586 | control->ClearAll(); | ||
| 587 | } | ||
| 588 | } | ||
| 589 | |||
| 590 | void CGUIDialogAddonSettings::CreateSections() | ||
| 591 | { | ||
| 592 | CGUIControlGroupList *group = dynamic_cast<CGUIControlGroupList *>(GetControl(CONTROL_SECTION_AREA)); | ||
| 593 | CGUIButtonControl *originalButton = dynamic_cast<CGUIButtonControl *>(GetControl(CONTROL_DEFAULT_SECTION_BUTTON)); | ||
| 594 | if (!m_addon) | ||
| 595 | return; | ||
| 596 | |||
| 597 | if (originalButton) | ||
| 598 | originalButton->SetVisible(false); | ||
| 599 | |||
| 600 | // clear the category group | ||
| 601 | FreeSections(); | ||
| 602 | |||
| 603 | // grab our categories | ||
| 604 | const TiXmlElement *category = m_addon->GetSettingsXML()->FirstChildElement("category"); | ||
| 605 | if (!category) // add a default one... | ||
| 606 | category = m_addon->GetSettingsXML(); | ||
| 607 | |||
| 608 | int buttonID = CONTROL_START_SECTION; | ||
| 609 | while (category) | ||
| 610 | { // add a category | ||
| 611 | CGUIButtonControl *button = originalButton ? originalButton->Clone() : NULL; | ||
| 612 | |||
| 613 | std::string label = GetString(category->Attribute("label")); | ||
| 614 | if (label.empty()) | ||
| 615 | label = g_localizeStrings.Get(128); | ||
| 616 | |||
| 617 | if (buttonID >= CONTROL_START_SETTING) | ||
| 618 | { | ||
| 619 | CLog::Log(LOGERROR, "%s - cannot have more than %d categories - simplify your addon!", __FUNCTION__, CONTROL_START_SETTING - CONTROL_START_SECTION); | ||
| 620 | break; | ||
| 621 | } | ||
| 622 | |||
| 623 | // add the category button | ||
| 624 | if (button && group) | ||
| 625 | { | ||
| 626 | button->SetID(buttonID++); | ||
| 627 | button->SetLabel(label); | ||
| 628 | button->SetVisible(true); | ||
| 629 | group->AddControl(button); | ||
| 630 | } | ||
| 631 | |||
| 632 | // grab a local copy of all the settings in this category | ||
| 633 | const TiXmlElement *setting = category->FirstChildElement("setting"); | ||
| 634 | while (setting) | ||
| 635 | { | ||
| 636 | const std::string id = XMLUtils::GetAttribute(setting, "id"); | ||
| 637 | if (!id.empty()) | ||
| 638 | m_settings[id] = m_addon->GetSetting(id); | ||
| 639 | setting = setting->NextSiblingElement("setting"); | ||
| 640 | } | ||
| 641 | category = category->NextSiblingElement("category"); | ||
| 642 | } | ||
| 643 | m_totalSections = buttonID - CONTROL_START_SECTION; | ||
| 644 | } | ||
| 645 | |||
| 646 | void CGUIDialogAddonSettings::CreateControls() | ||
| 647 | { | ||
| 648 | FreeControls(); | ||
| 649 | |||
| 650 | CGUISpinControlEx *pOriginalSpin = dynamic_cast<CGUISpinControlEx*>(GetControl(CONTROL_DEFAULT_SPIN)); | ||
| 651 | CGUIRadioButtonControl *pOriginalRadioButton = dynamic_cast<CGUIRadioButtonControl *>(GetControl(CONTROL_DEFAULT_RADIOBUTTON)); | ||
| 652 | CGUIButtonControl *pOriginalButton = dynamic_cast<CGUIButtonControl *>(GetControl(CONTROL_DEFAULT_BUTTON)); | ||
| 653 | CGUIImage *pOriginalImage = dynamic_cast<CGUIImage *>(GetControl(CONTROL_DEFAULT_SEPARATOR)); | ||
| 654 | CGUILabelControl *pOriginalLabel = dynamic_cast<CGUILabelControl *>(GetControl(CONTROL_DEFAULT_LABEL_SEPARATOR)); | ||
| 655 | CGUISettingsSliderControl *pOriginalSlider = dynamic_cast<CGUISettingsSliderControl *>(GetControl(CONTROL_DEFAULT_SLIDER)); | ||
| 656 | |||
| 657 | if (!m_addon || !pOriginalSpin || !pOriginalRadioButton || !pOriginalButton || !pOriginalImage | ||
| 658 | || !pOriginalLabel || !pOriginalSlider) | ||
| 659 | return; | ||
| 660 | |||
| 661 | pOriginalSpin->SetVisible(false); | ||
| 662 | pOriginalRadioButton->SetVisible(false); | ||
| 663 | pOriginalButton->SetVisible(false); | ||
| 664 | pOriginalImage->SetVisible(false); | ||
| 665 | pOriginalLabel->SetVisible(false); | ||
| 666 | pOriginalSlider->SetVisible(false); | ||
| 667 | |||
| 668 | CGUIControlGroupList *group = dynamic_cast<CGUIControlGroupList *>(GetControl(CONTROL_SETTINGS_AREA)); | ||
| 669 | if (!group) | ||
| 670 | return; | ||
| 671 | |||
| 672 | // set our dialog heading | ||
| 673 | SET_CONTROL_LABEL(CONTROL_HEADING_LABEL, m_strHeading); | ||
| 674 | |||
| 675 | CGUIControl* pControl = NULL; | ||
| 676 | int controlId = CONTROL_START_SETTING; | ||
| 677 | const TiXmlElement *setting = GetFirstSetting(); | ||
| 678 | while (setting) | ||
| 679 | { | ||
| 680 | const std::string type = XMLUtils::GetAttribute(setting, "type"); | ||
| 681 | const std::string id = XMLUtils::GetAttribute(setting, "id"); | ||
| 682 | const std::string values = XMLUtils::GetAttribute(setting, "values"); | ||
| 683 | const std::string lvalues = XMLUtils::GetAttribute(setting, "lvalues"); | ||
| 684 | const std::string entries = XMLUtils::GetAttribute(setting, "entries"); | ||
| 685 | const std::string defaultVal = XMLUtils::GetAttribute(setting, "default"); | ||
| 686 | const std::string subsetting = XMLUtils::GetAttribute(setting, "subsetting"); | ||
| 687 | const std::string label = GetString(setting->Attribute("label"), subsetting == "true"); | ||
| 688 | |||
| 689 | bool bSort = XMLUtils::GetAttribute(setting, "sort") == "yes"; | ||
| 690 | if (!type.empty()) | ||
| 691 | { | ||
| 692 | bool isAddonSetting = false; | ||
| 693 | if (type == "text" || type == "ipaddress" | ||
| 694 | || type == "number" || type == "video" | ||
| 695 | || type == "audio" || type == "image" | ||
| 696 | || type == "folder" || type == "executable" | ||
| 697 | || type == "file" || type == "action" | ||
| 698 | || type == "date" || type == "time" | ||
| 699 | || type == "select" || (isAddonSetting = type == "addon")) | ||
| 700 | { | ||
| 701 | pControl = new CGUIButtonControl(*pOriginalButton); | ||
| 702 | if (!pControl) return; | ||
| 703 | ((CGUIButtonControl *)pControl)->SetLabel(label); | ||
| 704 | if (!id.empty()) | ||
| 705 | { | ||
| 706 | std::string value = m_settings[id]; | ||
| 707 | m_buttonValues[id] = value; | ||
| 708 | // get any option to test for hidden | ||
| 709 | const std::string option = XMLUtils::GetAttribute(setting, "option"); | ||
| 710 | if (option == "urlencoded") | ||
| 711 | value = CURL::Decode(value); | ||
| 712 | else if (option == "hidden") | ||
| 713 | { | ||
| 714 | std::string hiddenText; | ||
| 715 | hiddenText.append(value.size(), L'*'); | ||
| 716 | ((CGUIButtonControl *)pControl)->SetLabel2(hiddenText); | ||
| 717 | } | ||
| 718 | else | ||
| 719 | { | ||
| 720 | if (isAddonSetting) | ||
| 721 | ((CGUIButtonControl *)pControl)->SetLabel2(GetAddonNames(value)); | ||
| 722 | else if (type == "select" && !lvalues.empty()) | ||
| 723 | { | ||
| 724 | vector<string> valuesVec = StringUtils::Split(lvalues, '|'); | ||
| 725 | int selected = atoi(value.c_str()); | ||
| 726 | if (selected >= 0 && selected < (int)valuesVec.size()) | ||
| 727 | { | ||
| 728 | std::string label = m_addon->GetString(atoi(valuesVec[selected].c_str())); | ||
| 729 | if (label.empty()) | ||
| 730 | label = g_localizeStrings.Get(atoi(valuesVec[selected].c_str())); | ||
| 731 | ((CGUIButtonControl *)pControl)->SetLabel2(label); | ||
| 732 | } | ||
| 733 | } | ||
| 734 | else | ||
| 735 | ((CGUIButtonControl *)pControl)->SetLabel2(value); | ||
| 736 | } | ||
| 737 | } | ||
| 738 | else | ||
| 739 | ((CGUIButtonControl *)pControl)->SetLabel2(defaultVal); | ||
| 740 | } | ||
| 741 | else if (type == "bool" && !id.empty()) | ||
| 742 | { | ||
| 743 | pControl = new CGUIRadioButtonControl(*pOriginalRadioButton); | ||
| 744 | if (!pControl) return; | ||
| 745 | ((CGUIRadioButtonControl *)pControl)->SetLabel(label); | ||
| 746 | ((CGUIRadioButtonControl *)pControl)->SetSelected(m_settings[id] == "true"); | ||
| 747 | } | ||
| 748 | else if ((type == "enum" || type == "labelenum") && !id.empty()) | ||
| 749 | { | ||
| 750 | vector<std::string> valuesVec; | ||
| 751 | vector<std::string> entryVec; | ||
| 752 | |||
| 753 | pControl = new CGUISpinControlEx(*pOriginalSpin); | ||
| 754 | if (!pControl) return; | ||
| 755 | ((CGUISpinControlEx *)pControl)->SetText(label); | ||
| 756 | |||
| 757 | if (!lvalues.empty()) | ||
| 758 | StringUtils::Tokenize(lvalues, valuesVec, "|"); | ||
| 759 | else if (values == "$HOURS") | ||
| 760 | { | ||
| 761 | for (unsigned int i = 0; i < 24; i++) | ||
| 762 | { | ||
| 763 | CDateTime time(2000, 1, 1, i, 0, 0); | ||
| 764 | valuesVec.push_back(g_infoManager.LocalizeTime(time, TIME_FORMAT_HH_MM_XX)); | ||
| 765 | } | ||
| 766 | } | ||
| 767 | else | ||
| 768 | StringUtils::Tokenize(values, valuesVec, "|"); | ||
| 769 | if (!entries.empty()) | ||
| 770 | StringUtils::Tokenize(entries, entryVec, "|"); | ||
| 771 | |||
| 772 | if(bSort && type == "labelenum") | ||
| 773 | std::sort(valuesVec.begin(), valuesVec.end(), sortstringbyname()); | ||
| 774 | |||
| 775 | for (unsigned int i = 0; i < valuesVec.size(); i++) | ||
| 776 | { | ||
| 777 | int iAdd = i; | ||
| 778 | if (entryVec.size() > i) | ||
| 779 | iAdd = atoi(entryVec[i].c_str()); | ||
| 780 | if (!lvalues.empty()) | ||
| 781 | { | ||
| 782 | std::string replace = m_addon->GetString(atoi(valuesVec[i].c_str())); | ||
| 783 | if (replace.empty()) | ||
| 784 | replace = g_localizeStrings.Get(atoi(valuesVec[i].c_str())); | ||
| 785 | ((CGUISpinControlEx *)pControl)->AddLabel(replace, iAdd); | ||
| 786 | } | ||
| 787 | else | ||
| 788 | ((CGUISpinControlEx *)pControl)->AddLabel(valuesVec[i], iAdd); | ||
| 789 | } | ||
| 790 | if (type == "labelenum") | ||
| 791 | { // need to run through all our settings and find the one that matches | ||
| 792 | ((CGUISpinControlEx*) pControl)->SetValueFromLabel(m_settings[id]); | ||
| 793 | } | ||
| 794 | else | ||
| 795 | ((CGUISpinControlEx*) pControl)->SetValue(atoi(m_settings[id].c_str())); | ||
| 796 | |||
| 797 | } | ||
| 798 | else if (type == "fileenum" && !id.empty()) | ||
| 799 | { | ||
| 800 | pControl = new CGUISpinControlEx(*pOriginalSpin); | ||
| 801 | if (!pControl) return; | ||
| 802 | ((CGUISpinControlEx *)pControl)->SetText(label); | ||
| 803 | ((CGUISpinControlEx *)pControl)->SetFloatValue(1.0f); | ||
| 804 | |||
| 805 | vector<std::string> items = GetFileEnumValues(values, XMLUtils::GetAttribute(setting, "mask"), XMLUtils::GetAttribute(setting, "option")); | ||
| 806 | for (unsigned int i = 0; i < items.size(); ++i) | ||
| 807 | { | ||
| 808 | ((CGUISpinControlEx *)pControl)->AddLabel(items[i], i); | ||
| 809 | if (StringUtils::EqualsNoCase(items[i], m_settings[id])) | ||
| 810 | ((CGUISpinControlEx *)pControl)->SetValue(i); | ||
| 811 | } | ||
| 812 | } | ||
| 813 | // Sample: <setting id="mysettingname" type="rangeofnum" label="30000" rangestart="0" rangeend="100" elements="11" valueformat="30001" default="0" /> | ||
| 814 | // in strings.xml: <string id="30001">%2.0f mp</string> | ||
| 815 | // creates 11 piece, text formated number labels from 0 to 100 | ||
| 816 | else if (type == "rangeofnum" && !id.empty()) | ||
| 817 | { | ||
| 818 | pControl = new CGUISpinControlEx(*pOriginalSpin); | ||
| 819 | if (!pControl) | ||
| 820 | return; | ||
| 821 | ((CGUISpinControlEx *)pControl)->SetText(label); | ||
| 822 | ((CGUISpinControlEx *)pControl)->SetFloatValue(1.0f); | ||
| 823 | |||
| 824 | double rangestart = 0, rangeend = 1; | ||
| 825 | setting->Attribute("rangestart", &rangestart); | ||
| 826 | setting->Attribute("rangeend", &rangeend); | ||
| 827 | |||
| 828 | int elements = 2; | ||
| 829 | setting->Attribute("elements", &elements); | ||
| 830 | |||
| 831 | std::string valueformat; | ||
| 832 | if (setting->Attribute("valueformat")) | ||
| 833 | valueformat = m_addon->GetString(atoi(setting->Attribute("valueformat"))); | ||
| 834 | for (int i = 0; i < elements; i++) | ||
| 835 | { | ||
| 836 | std::string valuestring; | ||
| 837 | if (elements < 2) | ||
| 838 | valuestring = StringUtils::Format(valueformat.c_str(), rangestart); | ||
| 839 | else | ||
| 840 | valuestring = StringUtils::Format(valueformat.c_str(), rangestart+(rangeend-rangestart)/(elements-1)*i); | ||
| 841 | ((CGUISpinControlEx *)pControl)->AddLabel(valuestring, i); | ||
| 842 | } | ||
| 843 | ((CGUISpinControlEx *)pControl)->SetValue(atoi(m_settings[id].c_str())); | ||
| 844 | } | ||
| 845 | // Sample: <setting id="mysettingname" type="slider" label="30000" range="5,5,60" option="int" default="5"/> | ||
| 846 | // to make ints from 5-60 with 5 steps | ||
| 847 | else if (type == "slider" && !id.empty()) | ||
| 848 | { | ||
| 849 | pControl = new CGUISettingsSliderControl(*pOriginalSlider); | ||
| 850 | if (!pControl) return; | ||
| 851 | ((CGUISettingsSliderControl *)pControl)->SetText(label); | ||
| 852 | |||
| 853 | float fMin = 0.0f; | ||
| 854 | float fMax = 100.0f; | ||
| 855 | float fInc = 1.0f; | ||
| 856 | vector<std::string> range = StringUtils::Split(XMLUtils::GetAttribute(setting, "range"), ','); | ||
| 857 | if (range.size() > 1) | ||
| 858 | { | ||
| 859 | fMin = (float)atof(range[0].c_str()); | ||
| 860 | if (range.size() > 2) | ||
| 861 | { | ||
| 862 | fMax = (float)atof(range[2].c_str()); | ||
| 863 | fInc = (float)atof(range[1].c_str()); | ||
| 864 | } | ||
| 865 | else | ||
| 866 | fMax = (float)atof(range[1].c_str()); | ||
| 867 | } | ||
| 868 | |||
| 869 | std::string option = XMLUtils::GetAttribute(setting, "option"); | ||
| 870 | int iType=0; | ||
| 871 | |||
| 872 | if (option.empty() || StringUtils::EqualsNoCase(option, "float")) | ||
| 873 | iType = SLIDER_CONTROL_TYPE_FLOAT; | ||
| 874 | else if (StringUtils::EqualsNoCase(option, "int")) | ||
| 875 | iType = SLIDER_CONTROL_TYPE_INT; | ||
| 876 | else if (StringUtils::EqualsNoCase(option, "percent")) | ||
| 877 | iType = SLIDER_CONTROL_TYPE_PERCENTAGE; | ||
| 878 | |||
| 879 | ((CGUISettingsSliderControl *)pControl)->SetType(iType); | ||
| 880 | ((CGUISettingsSliderControl *)pControl)->SetFloatRange(fMin, fMax); | ||
| 881 | ((CGUISettingsSliderControl *)pControl)->SetFloatInterval(fInc); | ||
| 882 | ((CGUISettingsSliderControl *)pControl)->SetFloatValue((float)atof(m_settings[id].c_str())); | ||
| 883 | } | ||
| 884 | else if (type == "lsep") | ||
| 885 | { | ||
| 886 | pControl = new CGUILabelControl(*pOriginalLabel); | ||
| 887 | if (pControl) | ||
| 888 | ((CGUILabelControl *)pControl)->SetLabel(label); | ||
| 889 | } | ||
| 890 | else if (type == "sep") | ||
| 891 | pControl = new CGUIImage(*pOriginalImage); | ||
| 892 | } | ||
| 893 | |||
| 894 | if (pControl) | ||
| 895 | { | ||
| 896 | pControl->SetWidth(group->GetWidth()); | ||
| 897 | pControl->SetVisible(true); | ||
| 898 | pControl->SetID(controlId); | ||
| 899 | pControl->AllocResources(); | ||
| 900 | group->AddControl(pControl); | ||
| 901 | pControl = NULL; | ||
| 902 | } | ||
| 903 | |||
| 904 | setting = setting->NextSiblingElement("setting"); | ||
| 905 | controlId++; | ||
| 906 | } | ||
| 907 | EnableControls(); | ||
| 908 | } | ||
| 909 | |||
| 910 | std::string CGUIDialogAddonSettings::GetAddonNames(const std::string& addonIDslist) const | ||
| 911 | { | ||
| 912 | std::string retVal; | ||
| 913 | vector<string> addons = StringUtils::Split(addonIDslist, ','); | ||
| 914 | for (vector<string>::const_iterator it = addons.begin(); it != addons.end() ; ++it) | ||
| 915 | { | ||
| 916 | if (!retVal.empty()) | ||
| 917 | retVal += ", "; | ||
| 918 | AddonPtr addon; | ||
| 919 | if (CAddonMgr::Get().GetAddon(*it ,addon)) | ||
| 920 | retVal += addon->Name(); | ||
| 921 | else | ||
| 922 | retVal += *it; | ||
| 923 | } | ||
| 924 | return retVal; | ||
| 925 | } | ||
| 926 | |||
| 927 | vector<std::string> CGUIDialogAddonSettings::GetFileEnumValues(const std::string &path, const std::string &mask, const std::string &options) const | ||
| 928 | { | ||
| 929 | // Create our base path, used for type "fileenum" settings | ||
| 930 | // replace $PROFILE with the profile path of the plugin/script | ||
| 931 | std::string fullPath = path; | ||
| 932 | if (fullPath.find("$PROFILE") != std::string::npos) | ||
| 933 | StringUtils::Replace(fullPath, "$PROFILE", m_addon->Profile()); | ||
| 934 | else | ||
| 935 | fullPath = URIUtils::AddFileToFolder(m_addon->Path(), path); | ||
| 936 | |||
| 937 | bool hideExtensions = StringUtils::EqualsNoCase(options, "hideext"); | ||
| 938 | // fetch directory | ||
| 939 | CFileItemList items; | ||
| 940 | if (!mask.empty()) | ||
| 941 | CDirectory::GetDirectory(fullPath, items, mask, XFILE::DIR_FLAG_NO_FILE_DIRS); | ||
| 942 | else | ||
| 943 | CDirectory::GetDirectory(fullPath, items, "", XFILE::DIR_FLAG_NO_FILE_DIRS); | ||
| 944 | |||
| 945 | vector<std::string> values; | ||
| 946 | for (int i = 0; i < items.Size(); ++i) | ||
| 947 | { | ||
| 948 | CFileItemPtr pItem = items[i]; | ||
| 949 | if ((mask == "/" && pItem->m_bIsFolder) || !pItem->m_bIsFolder) | ||
| 950 | { | ||
| 951 | if (hideExtensions) | ||
| 952 | pItem->RemoveExtension(); | ||
| 953 | values.push_back(pItem->GetLabel()); | ||
| 954 | } | ||
| 955 | } | ||
| 956 | return values; | ||
| 957 | } | ||
| 958 | |||
| 959 | // Go over all the settings and set their enabled condition according to the values of the enabled attribute | ||
| 960 | void CGUIDialogAddonSettings::EnableControls() | ||
| 961 | { | ||
| 962 | int controlId = CONTROL_START_SETTING; | ||
| 963 | const TiXmlElement *setting = GetFirstSetting(); | ||
| 964 | while (setting) | ||
| 965 | { | ||
| 966 | const CGUIControl* control = GetControl(controlId); | ||
| 967 | if (control) | ||
| 968 | { | ||
| 969 | // set enable status | ||
| 970 | const char *enable = setting->Attribute("enable"); | ||
| 971 | if (enable) | ||
| 972 | ((CGUIControl*) control)->SetEnabled(GetCondition(enable, controlId)); | ||
| 973 | else | ||
| 974 | ((CGUIControl*) control)->SetEnabled(true); | ||
| 975 | // set visible status | ||
| 976 | const char *visible = setting->Attribute("visible"); | ||
| 977 | if (visible) | ||
| 978 | ((CGUIControl*) control)->SetVisible(GetCondition(visible, controlId)); | ||
| 979 | else | ||
| 980 | ((CGUIControl*) control)->SetVisible(true); | ||
| 981 | } | ||
| 982 | setting = setting->NextSiblingElement("setting"); | ||
| 983 | controlId++; | ||
| 984 | } | ||
| 985 | } | ||
| 986 | |||
| 987 | bool CGUIDialogAddonSettings::GetCondition(const std::string &condition, const int controlId) | ||
| 988 | { | ||
| 989 | if (condition.empty()) return true; | ||
| 990 | |||
| 991 | bool bCondition = true; | ||
| 992 | bool bCompare = true; | ||
| 993 | bool bControlDependend = false;//flag if the condition depends on another control | ||
| 994 | vector<std::string> conditionVec; | ||
| 995 | |||
| 996 | if (condition.find("+") != std::string::npos) | ||
| 997 | StringUtils::Tokenize(condition, conditionVec, "+"); | ||
| 998 | else | ||
| 999 | { | ||
| 1000 | bCondition = false; | ||
| 1001 | bCompare = false; | ||
| 1002 | StringUtils::Tokenize(condition, conditionVec, "|"); | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | for (unsigned int i = 0; i < conditionVec.size(); i++) | ||
| 1006 | { | ||
| 1007 | vector<std::string> condVec; | ||
| 1008 | if (!TranslateSingleString(conditionVec[i], condVec)) continue; | ||
| 1009 | |||
| 1010 | const CGUIControl* control2 = GetControl(controlId + atoi(condVec[1].c_str())); | ||
| 1011 | if (!control2) | ||
| 1012 | continue; | ||
| 1013 | |||
| 1014 | bControlDependend = true; //once we are here - this condition depends on another control | ||
| 1015 | |||
| 1016 | std::string value; | ||
| 1017 | switch (control2->GetControlType()) | ||
| 1018 | { | ||
| 1019 | case CGUIControl::GUICONTROL_BUTTON: | ||
| 1020 | value = ((CGUIButtonControl*) control2)->GetLabel2(); | ||
| 1021 | break; | ||
| 1022 | case CGUIControl::GUICONTROL_RADIO: | ||
| 1023 | value = ((CGUIRadioButtonControl*) control2)->IsSelected() ? "true" : "false"; | ||
| 1024 | break; | ||
| 1025 | case CGUIControl::GUICONTROL_SPINEX: | ||
| 1026 | if (((CGUISpinControlEx*) control2)->GetFloatValue() > 0.0f) | ||
| 1027 | value = ((CGUISpinControlEx*) control2)->GetLabel(); | ||
| 1028 | else | ||
| 1029 | value = StringUtils::Format("%i", ((CGUISpinControlEx*) control2)->GetValue()); | ||
| 1030 | break; | ||
| 1031 | default: | ||
| 1032 | break; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | if (condVec[0] == "eq") | ||
| 1036 | { | ||
| 1037 | if (bCompare) | ||
| 1038 | bCondition &= StringUtils::EqualsNoCase(value, condVec[2]); | ||
| 1039 | else | ||
| 1040 | bCondition |= StringUtils::EqualsNoCase(value, condVec[2]); | ||
| 1041 | } | ||
| 1042 | else if (condVec[0] == "!eq") | ||
| 1043 | { | ||
| 1044 | if (bCompare) | ||
| 1045 | bCondition &= !StringUtils::EqualsNoCase(value, condVec[2]); | ||
| 1046 | else | ||
| 1047 | bCondition |= !StringUtils::EqualsNoCase(value, condVec[2]); | ||
| 1048 | } | ||
| 1049 | else if (condVec[0] == "gt") | ||
| 1050 | { | ||
| 1051 | if (bCompare) | ||
| 1052 | bCondition &= (atoi(value.c_str()) > atoi(condVec[2].c_str())); | ||
| 1053 | else | ||
| 1054 | bCondition |= (atoi(value.c_str()) > atoi(condVec[2].c_str())); | ||
| 1055 | } | ||
| 1056 | else if (condVec[0] == "lt") | ||
| 1057 | { | ||
| 1058 | if (bCompare) | ||
| 1059 | bCondition &= (atoi(value.c_str()) < atoi(condVec[2].c_str())); | ||
| 1060 | else | ||
| 1061 | bCondition |= (atoi(value.c_str()) < atoi(condVec[2].c_str())); | ||
| 1062 | } | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | if (!bControlDependend)//if condition doesn't depend on another control - try if its an infobool expression | ||
| 1066 | { | ||
| 1067 | bCondition = g_infoManager.EvaluateBool(condition); | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | return bCondition; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | bool CGUIDialogAddonSettings::TranslateSingleString(const std::string &strCondition, vector<std::string> &condVec) | ||
| 1074 | { | ||
| 1075 | std::string strTest = strCondition; | ||
| 1076 | StringUtils::ToLower(strTest); | ||
| 1077 | StringUtils::Trim(strTest); | ||
| 1078 | |||
| 1079 | size_t pos1 = strTest.find("("); | ||
| 1080 | size_t pos2 = strTest.find(",", pos1); | ||
| 1081 | size_t pos3 = strTest.find(")", pos2); | ||
| 1082 | if (pos1 != std::string::npos && | ||
| 1083 | pos2 != std::string::npos && | ||
| 1084 | pos3 != std::string::npos) | ||
| 1085 | { | ||
| 1086 | condVec.push_back(strTest.substr(0, pos1)); | ||
| 1087 | condVec.push_back(strTest.substr(pos1 + 1, pos2 - pos1 - 1)); | ||
| 1088 | condVec.push_back(strTest.substr(pos2 + 1, pos3 - pos2 - 1)); | ||
| 1089 | return true; | ||
| 1090 | } | ||
| 1091 | return false; | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | std::string CGUIDialogAddonSettings::GetString(const char *value, bool subSetting) const | ||
| 1095 | { | ||
| 1096 | if (!value) | ||
| 1097 | return ""; | ||
| 1098 | std::string prefix(subSetting ? "- " : ""); | ||
| 1099 | if (StringUtils::IsNaturalNumber(value)) | ||
| 1100 | return prefix + m_addon->GetString(atoi(value)); | ||
| 1101 | return prefix + value; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | // Go over all the settings and set their default values | ||
| 1105 | void CGUIDialogAddonSettings::SetDefaultSettings() | ||
| 1106 | { | ||
| 1107 | if(!m_addon) | ||
| 1108 | return; | ||
| 1109 | |||
| 1110 | const TiXmlElement *category = m_addon->GetSettingsXML()->FirstChildElement("category"); | ||
| 1111 | if (!category) // add a default one... | ||
| 1112 | category = m_addon->GetSettingsXML(); | ||
| 1113 | |||
| 1114 | while (category) | ||
| 1115 | { | ||
| 1116 | const TiXmlElement *setting = category->FirstChildElement("setting"); | ||
| 1117 | while (setting) | ||
| 1118 | { | ||
| 1119 | const std::string id = XMLUtils::GetAttribute(setting, "id"); | ||
| 1120 | const std::string type = XMLUtils::GetAttribute(setting, "type"); | ||
| 1121 | const char *value = setting->Attribute("default"); | ||
| 1122 | if (!id.empty()) | ||
| 1123 | { | ||
| 1124 | if (value) | ||
| 1125 | m_settings[id] = value; | ||
| 1126 | else if (type == "bool") | ||
| 1127 | m_settings[id] = "false"; | ||
| 1128 | else if (type == "slider" || type == "enum") | ||
| 1129 | m_settings[id] = "0"; | ||
| 1130 | else | ||
| 1131 | m_settings[id] = ""; | ||
| 1132 | } | ||
| 1133 | setting = setting->NextSiblingElement("setting"); | ||
| 1134 | } | ||
| 1135 | category = category->NextSiblingElement("category"); | ||
| 1136 | } | ||
| 1137 | CreateControls(); | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | const TiXmlElement *CGUIDialogAddonSettings::GetFirstSetting() const | ||
| 1141 | { | ||
| 1142 | const TiXmlElement *category = m_addon->GetSettingsXML()->FirstChildElement("category"); | ||
| 1143 | if (!category) | ||
| 1144 | category = m_addon->GetSettingsXML(); | ||
| 1145 | for (unsigned int i = 0; i < m_currentSection && category; i++) | ||
| 1146 | category = category->NextSiblingElement("category"); | ||
| 1147 | if (category) | ||
| 1148 | return category->FirstChildElement("setting"); | ||
| 1149 | return NULL; | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | void CGUIDialogAddonSettings::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions) | ||
| 1153 | { | ||
| 1154 | // update status of current section button | ||
| 1155 | bool alphaFaded = false; | ||
| 1156 | CGUIControl *control = GetFirstFocusableControl(CONTROL_START_SECTION + m_currentSection); | ||
| 1157 | if (control && !control->HasFocus()) | ||
| 1158 | { | ||
| 1159 | if (control->GetControlType() == CGUIControl::GUICONTROL_BUTTON) | ||
| 1160 | { | ||
| 1161 | control->SetFocus(true); | ||
| 1162 | ((CGUIButtonControl *)control)->SetAlpha(0x80); | ||
| 1163 | alphaFaded = true; | ||
| 1164 | } | ||
| 1165 | else if (control->GetControlType() == CGUIControl::GUICONTROL_TOGGLEBUTTON) | ||
| 1166 | { | ||
| 1167 | control->SetFocus(true); | ||
| 1168 | ((CGUIButtonControl *)control)->SetSelected(true); | ||
| 1169 | alphaFaded = true; | ||
| 1170 | } | ||
| 1171 | } | ||
| 1172 | CGUIDialogBoxBase::DoProcess(currentTime, dirtyregions); | ||
| 1173 | if (alphaFaded && m_active) // dialog may close | ||
| 1174 | { | ||
| 1175 | control->SetFocus(false); | ||
| 1176 | if (control->GetControlType() == CGUIControl::GUICONTROL_BUTTON) | ||
| 1177 | ((CGUIButtonControl *)control)->SetAlpha(0xFF); | ||
| 1178 | else | ||
| 1179 | ((CGUIButtonControl *)control)->SetSelected(false); | ||
| 1180 | } | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | std::string CGUIDialogAddonSettings::GetCurrentID() const | ||
| 1184 | { | ||
| 1185 | if (m_addon) | ||
| 1186 | return m_addon->ID(); | ||
| 1187 | return ""; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | int CGUIDialogAddonSettings::GetDefaultLabelID(int controlId) const | ||
| 1191 | { | ||
| 1192 | if (controlId == ID_BUTTON_OK) | ||
| 1193 | return 186; | ||
| 1194 | else if (controlId == ID_BUTTON_CANCEL) | ||
| 1195 | return 222; | ||
| 1196 | else if (controlId == ID_BUTTON_DEFAULT) | ||
| 1197 | return 409; | ||
| 1198 | |||
| 1199 | return CGUIDialogBoxBase::GetDefaultLabelID(controlId); | ||
| 1200 | } | ||
