Merge pull request #24470 from fuzzard/release_20.3
[xbmc.git] / xbmc / input / KeyboardLayoutManager.cpp
blob66ed817cf18cbf29626a5387d61d2b0e770f6c30
1 /*
2 * Copyright (C) 2015-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "KeyboardLayoutManager.h"
11 #include "FileItem.h"
12 #include "ServiceBroker.h"
13 #include "URL.h"
14 #include "filesystem/Directory.h"
15 #include "settings/lib/Setting.h"
16 #include "settings/lib/SettingDefinitions.h"
17 #include "utils/XBMCTinyXML.h"
18 #include "utils/log.h"
20 #include <algorithm>
22 #define KEYBOARD_LAYOUTS_PATH "special://xbmc/system/keyboardlayouts"
24 CKeyboardLayoutManager::~CKeyboardLayoutManager()
26 Unload();
29 bool CKeyboardLayoutManager::Load(const std::string& path /* = "" */)
31 std::string layoutDirectory = path;
32 if (layoutDirectory.empty())
33 layoutDirectory = KEYBOARD_LAYOUTS_PATH;
35 if (!XFILE::CDirectory::Exists(layoutDirectory))
37 CLog::Log(LOGWARNING,
38 "CKeyboardLayoutManager: unable to load keyboard layouts from non-existing directory "
39 "\"{}\"",
40 layoutDirectory);
41 return false;
44 CFileItemList layouts;
45 if (!XFILE::CDirectory::GetDirectory(CURL(layoutDirectory), layouts, ".xml",
46 XFILE::DIR_FLAG_DEFAULTS) ||
47 layouts.IsEmpty())
49 CLog::Log(LOGWARNING, "CKeyboardLayoutManager: no keyboard layouts found in {}",
50 layoutDirectory);
51 return false;
54 CLog::Log(LOGINFO, "CKeyboardLayoutManager: loading keyboard layouts from {}...",
55 layoutDirectory);
56 size_t oldLayoutCount = m_layouts.size();
57 for (int i = 0; i < layouts.Size(); i++)
59 std::string layoutPath = layouts[i]->GetPath();
60 if (layoutPath.empty())
61 continue;
63 CXBMCTinyXML xmlDoc;
64 if (!xmlDoc.LoadFile(layoutPath))
66 CLog::Log(LOGWARNING, "CKeyboardLayoutManager: unable to open {}", layoutPath);
67 continue;
70 const TiXmlElement* rootElement = xmlDoc.RootElement();
71 if (rootElement == NULL)
73 CLog::Log(LOGWARNING, "CKeyboardLayoutManager: missing or invalid XML root element in {}",
74 layoutPath);
75 continue;
78 if (rootElement->ValueStr() != "keyboardlayouts")
80 CLog::Log(LOGWARNING, "CKeyboardLayoutManager: unexpected XML root element \"{}\" in {}",
81 rootElement->Value(), layoutPath);
82 continue;
85 const TiXmlElement* layoutElement = rootElement->FirstChildElement("layout");
86 while (layoutElement != NULL)
88 CKeyboardLayout layout;
89 if (!layout.Load(layoutElement))
90 CLog::Log(LOGWARNING, "CKeyboardLayoutManager: failed to load {}", layoutPath);
91 else if (m_layouts.find(layout.GetIdentifier()) != m_layouts.end())
92 CLog::Log(LOGWARNING,
93 "CKeyboardLayoutManager: duplicate layout with identifier \"{}\" in {}",
94 layout.GetIdentifier(), layoutPath);
95 else
97 CLog::Log(LOGDEBUG, "CKeyboardLayoutManager: keyboard layout \"{}\" successfully loaded",
98 layout.GetIdentifier());
99 m_layouts.insert(std::make_pair(layout.GetIdentifier(), layout));
102 layoutElement = layoutElement->NextSiblingElement();
106 return m_layouts.size() > oldLayoutCount;
109 void CKeyboardLayoutManager::Unload()
111 m_layouts.clear();
114 bool CKeyboardLayoutManager::GetLayout(const std::string& name, CKeyboardLayout& layout) const
116 if (name.empty())
117 return false;
119 KeyboardLayouts::const_iterator it = m_layouts.find(name);
120 if (it == m_layouts.end())
121 return false;
123 layout = it->second;
124 return true;
127 namespace
129 inline bool LayoutSort(const StringSettingOption& i, const StringSettingOption& j)
131 return (i.value < j.value);
133 } // namespace
135 void CKeyboardLayoutManager::SettingOptionsKeyboardLayoutsFiller(
136 const SettingConstPtr& setting,
137 std::vector<StringSettingOption>& list,
138 std::string& current,
139 void* data)
141 for (const auto& it : CServiceBroker::GetKeyboardLayoutManager()->m_layouts)
143 std::string name = it.second.GetName();
144 list.emplace_back(name, name);
147 std::sort(list.begin(), list.end(), LayoutSort);