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.
9 #include "KeyboardLayoutManager.h"
12 #include "ServiceBroker.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"
22 #define KEYBOARD_LAYOUTS_PATH "special://xbmc/system/keyboardlayouts"
24 CKeyboardLayoutManager::~CKeyboardLayoutManager()
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
))
38 "CKeyboardLayoutManager: unable to load keyboard layouts from non-existing directory "
44 CFileItemList layouts
;
45 if (!XFILE::CDirectory::GetDirectory(CURL(layoutDirectory
), layouts
, ".xml",
46 XFILE::DIR_FLAG_DEFAULTS
) ||
49 CLog::Log(LOGWARNING
, "CKeyboardLayoutManager: no keyboard layouts found in {}",
54 CLog::Log(LOGINFO
, "CKeyboardLayoutManager: loading keyboard layouts from {}...",
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())
64 if (!xmlDoc
.LoadFile(layoutPath
))
66 CLog::Log(LOGWARNING
, "CKeyboardLayoutManager: unable to open {}", layoutPath
);
70 const TiXmlElement
* rootElement
= xmlDoc
.RootElement();
71 if (rootElement
== NULL
)
73 CLog::Log(LOGWARNING
, "CKeyboardLayoutManager: missing or invalid XML root element in {}",
78 if (rootElement
->ValueStr() != "keyboardlayouts")
80 CLog::Log(LOGWARNING
, "CKeyboardLayoutManager: unexpected XML root element \"{}\" in {}",
81 rootElement
->Value(), layoutPath
);
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())
93 "CKeyboardLayoutManager: duplicate layout with identifier \"{}\" in {}",
94 layout
.GetIdentifier(), layoutPath
);
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()
114 bool CKeyboardLayoutManager::GetLayout(const std::string
& name
, CKeyboardLayout
& layout
) const
119 KeyboardLayouts::const_iterator it
= m_layouts
.find(name
);
120 if (it
== m_layouts
.end())
129 inline bool LayoutSort(const StringSettingOption
& i
, const StringSettingOption
& j
)
131 return (i
.value
< j
.value
);
135 void CKeyboardLayoutManager::SettingOptionsKeyboardLayoutsFiller(
136 const SettingConstPtr
& setting
,
137 std::vector
<StringSettingOption
>& list
,
138 std::string
& current
,
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
);