aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kodi.xcodeproj/project.pbxproj10
-rw-r--r--project/VS2010Express/XBMC.vcxproj4
-rw-r--r--project/VS2010Express/XBMC.vcxproj.filters8
-rw-r--r--system/keyboardlayouts/keyboardlayouts.xml (renamed from system/keyboardlayouts.xml)0
-rw-r--r--xbmc/Application.cpp8
-rw-r--r--xbmc/dialogs/GUIDialogKeyboardGeneric.cpp24
-rw-r--r--xbmc/input/KeyboardLayout.cpp100
-rw-r--r--xbmc/input/KeyboardLayout.h44
-rw-r--r--xbmc/input/KeyboardLayoutManager.cpp134
-rw-r--r--xbmc/input/KeyboardLayoutManager.h52
-rw-r--r--xbmc/input/Makefile1
-rw-r--r--xbmc/settings/Settings.cpp4
12 files changed, 275 insertions, 114 deletions
diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj
index 33a3cf38ff..80c885578c 100644
--- a/Kodi.xcodeproj/project.pbxproj
+++ b/Kodi.xcodeproj/project.pbxproj
@@ -180,6 +180,9 @@
3802709A13D5A653009493DD /* SystemClock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3802709813D5A653009493DD /* SystemClock.cpp */; };
384718D81325BA04000486D6 /* XBDateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 384718D61325BA04000486D6 /* XBDateTime.cpp */; };
38F4E57013CCCB3B00664821 /* Implementation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 38F4E56C13CCCB3B00664821 /* Implementation.cpp */; };
+ 395897151AAD94F00033D27C /* KeyboardLayoutManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395897131AAD94F00033D27C /* KeyboardLayoutManager.cpp */; };
+ 395897161AAD94F00033D27C /* KeyboardLayoutManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395897131AAD94F00033D27C /* KeyboardLayoutManager.cpp */; };
+ 395897171AAD94F00033D27C /* KeyboardLayoutManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395897131AAD94F00033D27C /* KeyboardLayoutManager.cpp */; };
395C29BC1A94733100EBC7AD /* Key.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C29BA1A94733100EBC7AD /* Key.cpp */; };
395C29BD1A94733100EBC7AD /* Key.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C29BA1A94733100EBC7AD /* Key.cpp */; };
395C29BE1A94733100EBC7AD /* Key.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C29BA1A94733100EBC7AD /* Key.cpp */; };
@@ -3664,6 +3667,8 @@
38F4E56C13CCCB3B00664821 /* Implementation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Implementation.cpp; sourceTree = "<group>"; };
38F4E56D13CCCB3B00664821 /* README.platform */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.platform; sourceTree = "<group>"; };
38F4E56E13CCCB3B00664821 /* ThreadLocal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocal.h; sourceTree = "<group>"; };
+ 395897131AAD94F00033D27C /* KeyboardLayoutManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyboardLayoutManager.cpp; sourceTree = "<group>"; };
+ 395897141AAD94F00033D27C /* KeyboardLayoutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyboardLayoutManager.h; sourceTree = "<group>"; };
395C29BA1A94733100EBC7AD /* Key.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Key.cpp; sourceTree = "<group>"; };
395C29BB1A94733100EBC7AD /* Key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Key.h; sourceTree = "<group>"; };
395C29BF1A98A0A000EBC7AD /* Webinterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Webinterface.cpp; sourceTree = "<group>"; };
@@ -6418,6 +6423,8 @@
395C29BB1A94733100EBC7AD /* Key.h */,
7CF80DC719710DC2003B2B34 /* KeyboardLayout.cpp */,
7CF80DC819710DC2003B2B34 /* KeyboardLayout.h */,
+ 395897131AAD94F00033D27C /* KeyboardLayoutManager.cpp */,
+ 395897141AAD94F00033D27C /* KeyboardLayoutManager.h */,
18B7C8CF12942546009E7A26 /* KeyboardStat.cpp */,
18B7C8D012942546009E7A26 /* KeyboardStat.h */,
18B7C8D112942546009E7A26 /* MouseStat.cpp */,
@@ -10735,6 +10742,7 @@
E3A4780A0D29029A00F3C3A6 /* GUIDialogCache.cpp in Sources */,
395C29ED1A98A16300EBC7AD /* HTTPPythonInvoker.cpp in Sources */,
E3A4781A0D29032C00F3C3A6 /* GUIDialogAccessPoints.cpp in Sources */,
+ 395897151AAD94F00033D27C /* KeyboardLayoutManager.cpp in Sources */,
E36578880D3AA7B40033CC1C /* DVDPlayerCodec.cpp in Sources */,
E33206380D5070AA00435CE3 /* DVDDemuxVobsub.cpp in Sources */,
E33979960D62FD48004ECDDA /* DVDInputStreamTV.cpp in Sources */,
@@ -11817,6 +11825,7 @@
DFF0F24D17528350002DA3A4 /* SpecialProtocol.cpp in Sources */,
DFF0F24E17528350002DA3A4 /* SpecialProtocolDirectory.cpp in Sources */,
DFF0F24F17528350002DA3A4 /* SpecialProtocolFile.cpp in Sources */,
+ 395897171AAD94F00033D27C /* KeyboardLayoutManager.cpp in Sources */,
DFF0F25017528350002DA3A4 /* StackDirectory.cpp in Sources */,
DFF0F25317528350002DA3A4 /* udf25.cpp in Sources */,
DFF0F25417528350002DA3A4 /* UDFDirectory.cpp in Sources */,
@@ -12981,6 +12990,7 @@
E4991309174E5DAD00741B6D /* GUIRadioButtonControl.cpp in Sources */,
E499130A174E5DAD00741B6D /* GUIRenderingControl.cpp in Sources */,
E499130B174E5DAD00741B6D /* GUIResizeControl.cpp in Sources */,
+ 395897161AAD94F00033D27C /* KeyboardLayoutManager.cpp in Sources */,
395C2A251AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */,
E499130C174E5DAD00741B6D /* GUIRSSControl.cpp in Sources */,
E499130D174E5DAD00741B6D /* GUIScrollBarControl.cpp in Sources */,
diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj
index 128f32ac8e..9d35b9ee62 100644
--- a/project/VS2010Express/XBMC.vcxproj
+++ b/project/VS2010Express/XBMC.vcxproj
@@ -502,6 +502,7 @@
<ClCompile Include="..\..\xbmc\input\InputManager.cpp" />
<ClCompile Include="..\..\xbmc\input\Key.cpp" />
<ClCompile Include="..\..\xbmc\input\KeyboardLayout.cpp" />
+ <ClCompile Include="..\..\xbmc\input\KeyboardLayoutManager.cpp" />
<ClCompile Include="..\..\xbmc\input\KeyboardStat.cpp" />
<ClCompile Include="..\..\xbmc\input\MouseStat.cpp" />
<ClCompile Include="..\..\xbmc\input\touch\generic\GenericTouchActionHandler.cpp" />
@@ -904,6 +905,7 @@
<ClInclude Include="..\..\xbmc\IFileItemListModifier.h" />
<ClInclude Include="..\..\xbmc\input\InputManager.h" />
<ClInclude Include="..\..\xbmc\input\Key.h" />
+ <ClInclude Include="..\..\xbmc\input\KeyboardLayoutManager.h" />
<ClInclude Include="..\..\xbmc\input\touch\generic\GenericTouchActionHandler.h" />
<ClInclude Include="..\..\xbmc\input\touch\generic\GenericTouchSwipeDetector.h" />
<ClInclude Include="..\..\xbmc\input\touch\generic\IGenericTouchGestureDetector.h" />
@@ -2613,4 +2615,4 @@
</VisualStudio>
</ProjectExtensions>
<Import Project="$(SolutionDir)\$(ProjectFileName).targets.user" Condition="Exists('$(SolutionDir)\$(ProjectFileName).targets.user')" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters
index e3fbb2d569..6173801e46 100644
--- a/project/VS2010Express/XBMC.vcxproj.filters
+++ b/project/VS2010Express/XBMC.vcxproj.filters
@@ -3176,6 +3176,9 @@
<ClCompile Include="..\..\xbmc\utils\Speed.cpp">
<Filter>utils</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\input\KeyboardLayoutManager.cpp">
+ <Filter>input</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\xbmc\win32\pch.h">
@@ -6171,6 +6174,9 @@
<ClInclude Include="..\..\xbmc\utils\Speed.h">
<Filter>utils</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\input\KeyboardLayoutManager.h">
+ <Filter>input</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc">
@@ -6216,4 +6222,4 @@
<Filter>interfaces\swig</Filter>
</CustomBuild>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/system/keyboardlayouts.xml b/system/keyboardlayouts/keyboardlayouts.xml
index b1aa50835e..b1aa50835e 100644
--- a/system/keyboardlayouts.xml
+++ b/system/keyboardlayouts/keyboardlayouts.xml
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
index c974695699..a60c4827aa 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -100,6 +100,7 @@
#include "utils/SeekHandler.h"
#include "view/ViewStateSettings.h"
+#include "input/KeyboardLayoutManager.h"
#include "input/KeyboardStat.h"
#include "input/XBMC_vkeys.h"
#include "input/MouseStat.h"
@@ -704,6 +705,13 @@ bool CApplication::Create()
// Initialize after loading settings to get joystick deadzone setting
CInputManager::Get().InitializeInputs();
+ // load the keyboard layouts
+ if (!CKeyboardLayoutManager::Get().Load())
+ {
+ CLog::Log(LOGFATAL, "CApplication::Create: Unable to load keyboard layouts");
+ return false;
+ }
+
#if defined(TARGET_DARWIN_OSX)
// Configure and possible manually start the helper.
XBMCHelper::GetInstance().Configure();
diff --git a/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp b/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp
index a29cd46024..8c9b94896a 100644
--- a/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp
+++ b/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp
@@ -22,6 +22,7 @@
#include "input/XBMC_vkeys.h"
#include "guilib/GUIEditControl.h"
#include "guilib/GUIWindowManager.h"
+#include "input/KeyboardLayoutManager.h"
#include "input/Key.h"
#include "guilib/LocalizeStrings.h"
#include "GUIUserMessages.h"
@@ -90,15 +91,14 @@ void CGUIDialogKeyboardGeneric::OnInitWindow()
// fill in the keyboard layouts
m_currentLayout = 0;
m_layouts.clear();
- std::vector<CKeyboardLayout> keyLayouts = CKeyboardLayout::LoadLayouts();
- const CSetting *setting = CSettings::Get().GetSetting("locale.keyboardlayouts");
- std::vector<std::string> layouts;
- if (setting)
- layouts = StringUtils::Split(setting->ToString(), '|');
- for (std::vector<CKeyboardLayout>::const_iterator j = keyLayouts.begin(); j != keyLayouts.end(); ++j)
+ const KeyboardLayouts& keyboardLayouts = CKeyboardLayoutManager::Get().GetLayouts();
+ std::vector<CVariant> layoutNames = CSettings::Get().GetList("locale.keyboardlayouts");
+
+ for (std::vector<CVariant>::const_iterator layoutName = layoutNames.begin(); layoutName != layoutNames.end(); ++layoutName)
{
- if (std::find(layouts.begin(), layouts.end(), j->GetName()) != layouts.end())
- m_layouts.push_back(*j);
+ KeyboardLayouts::const_iterator keyboardLayout = keyboardLayouts.find(layoutName->asString());
+ if (keyboardLayout != keyboardLayouts.end())
+ m_layouts.push_back(keyboardLayout->second);
}
// set alphabetic (capitals)
@@ -318,14 +318,14 @@ void CGUIDialogKeyboardGeneric::UpdateButtons()
CKeyboardLayout layout = m_layouts.empty() ? CKeyboardLayout() : m_layouts[m_currentLayout];
SET_CONTROL_LABEL(CTL_BUTTON_LAYOUT, layout.GetName());
- unsigned int modifiers = CKeyboardLayout::MODIFIER_KEY_NONE;
+ unsigned int modifiers = CKeyboardLayout::ModifierKeyNone;
if ((m_keyType == CAPS && !m_bShift) || (m_keyType == LOWER && m_bShift))
- modifiers |= CKeyboardLayout::MODIFIER_KEY_SHIFT;
+ modifiers |= CKeyboardLayout::ModifierKeyShift;
if (m_keyType == SYMBOLS)
{
- modifiers |= CKeyboardLayout::MODIFIER_KEY_SYMBOL;
+ modifiers |= CKeyboardLayout::ModifierKeySymbol;
if (m_bShift)
- modifiers |= CKeyboardLayout::MODIFIER_KEY_SHIFT;
+ modifiers |= CKeyboardLayout::ModifierKeyShift;
}
for (unsigned int row = 0; row < BUTTONS_MAX_ROWS; row++)
diff --git a/xbmc/input/KeyboardLayout.cpp b/xbmc/input/KeyboardLayout.cpp
index 511c676b0e..67f149d980 100644
--- a/xbmc/input/KeyboardLayout.cpp
+++ b/xbmc/input/KeyboardLayout.cpp
@@ -18,53 +18,61 @@
*
*/
+#include <algorithm>
+#include <set>
+
#include "KeyboardLayout.h"
#include "settings/lib/Setting.h"
#include "utils/CharsetConverter.h"
#include "utils/StringUtils.h"
#include "utils/XBMCTinyXML.h"
-#include <set>
-#include <algorithm>
-#define KEYBOARD_LAYOUTS_XML "special://xbmc/system/keyboardlayouts.xml"
+CKeyboardLayout::CKeyboardLayout()
+{ }
-CKeyboardLayout::CKeyboardLayout() : m_name("")
+bool CKeyboardLayout::Load(const TiXmlElement* element)
{
-}
+ const char* name = element->Attribute("name");
+ if (name == NULL)
+ return false;
-CKeyboardLayout::CKeyboardLayout(const std::string &name, const TiXmlElement &element) : m_name(name)
-{
- const TiXmlElement *keyboard = element.FirstChildElement("keyboard");
- while (keyboard)
+ m_name = name;
+ if (m_name.empty())
+ return false;
+
+ const TiXmlElement *keyboard = element->FirstChildElement("keyboard");
+ while (keyboard != NULL)
{
// parse modifiers keys
std::set<unsigned int> modifierKeysSet;
- if (keyboard->Attribute("modifiers"))
+ const char* strModifiers = keyboard->Attribute("modifiers");
+ if (strModifiers != NULL)
{
- std::string modifiers = keyboard->Attribute("modifiers");
+ std::string modifiers = strModifiers;
StringUtils::ToLower(modifiers);
std::vector<std::string> variants = StringUtils::Split(modifiers, ",");
for (std::vector<std::string>::const_iterator itv = variants.begin(); itv != variants.end(); ++itv)
{
- unsigned int iKeys = MODIFIER_KEY_NONE;
+ unsigned int iKeys = ModifierKeyNone;
std::vector<std::string> keys = StringUtils::Split(*itv, "+");
for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it)
{
std::string strKey = *it;
if (strKey == "shift")
- iKeys |= MODIFIER_KEY_SHIFT;
+ iKeys |= ModifierKeyShift;
else if (strKey == "symbol")
- iKeys |= MODIFIER_KEY_SYMBOL;
+ iKeys |= ModifierKeySymbol;
}
+
modifierKeysSet.insert(iKeys);
}
}
// parse keyboard rows
const TiXmlNode *row = keyboard->FirstChild("row");
- while (row)
+ while (row != NULL)
{
if (!row->NoChildren())
{
@@ -76,27 +84,31 @@ CKeyboardLayout::CKeyboardLayout(const std::string &name, const TiXmlElement &el
m_keyboards[*it].push_back(chars);
}
else
- m_keyboards[MODIFIER_KEY_NONE].push_back(chars);
+ m_keyboards[ModifierKeyNone].push_back(chars);
}
+
row = row->NextSibling();
}
keyboard = keyboard->NextSiblingElement();
}
-}
-CKeyboardLayout::~CKeyboardLayout(void)
-{
+ if (m_keyboards.empty())
+ return false;
+ return true;
}
+CKeyboardLayout::~CKeyboardLayout()
+{ }
+
std::string CKeyboardLayout::GetCharAt(unsigned int row, unsigned int column, unsigned int modifiers) const
{
Keyboards::const_iterator mod = m_keyboards.find(modifiers);
- if (modifiers != MODIFIER_KEY_NONE && mod != m_keyboards.end() && mod->second.empty())
+ if (modifiers != ModifierKeyNone && mod != m_keyboards.end() && mod->second.empty())
{
// fallback to basic keyboard
- mod = m_keyboards.find(MODIFIER_KEY_NONE);
+ mod = m_keyboards.find(ModifierKeyNone);
}
if (mod != m_keyboards.end())
@@ -117,53 +129,11 @@ std::vector<std::string> CKeyboardLayout::BreakCharacters(const std::string &cha
std::vector<std::string> result;
// break into utf8 characters
std::u32string chars32 = g_charsetConverter.utf8ToUtf32(chars);
- for (size_t i = 0; i < chars32.size(); i++)
+ for (std::u32string::const_iterator it = chars32.begin(); it != chars32.end(); ++it)
{
- std::u32string char32(1, chars32[i]);
+ std::u32string char32(1, *it);
result.push_back(g_charsetConverter.utf32ToUtf8(char32));
}
- return result;
-}
-
-CKeyboardLayout CKeyboardLayout::Load(const std::string& layout)
-{
- std::vector<CKeyboardLayout> layouts = LoadLayouts();
- for (std::vector<CKeyboardLayout>::const_iterator it = layouts.begin(); it != layouts.end(); ++it)
- {
- if (it->GetName() == layout)
- return *it;
- }
- return CKeyboardLayout();
-}
-std::vector<CKeyboardLayout> CKeyboardLayout::LoadLayouts()
-{
- std::vector<CKeyboardLayout> result;
- CXBMCTinyXML xmlDoc;
- if (xmlDoc.LoadFile(KEYBOARD_LAYOUTS_XML))
- {
- const TiXmlElement* root = xmlDoc.RootElement();
- if (root && root->ValueStr() == "keyboardlayouts")
- {
- const TiXmlElement* layout = root->FirstChildElement("layout");
- while (layout)
- {
- if (layout->Attribute("name"))
- result.push_back(CKeyboardLayout(layout->Attribute("name"), *layout));
- layout = layout->NextSiblingElement("layout");
- }
- }
- }
return result;
}
-
-void CKeyboardLayout::SettingOptionsKeyboardLayoutsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current, void *data)
-{
- std::vector<CKeyboardLayout> layouts = LoadLayouts();
- for (std::vector<CKeyboardLayout>::const_iterator it = layouts.begin(); it != layouts.end(); ++it)
- {
- std::string name = it->GetName();
- list.push_back(make_pair(name, name));
- }
- std::sort(list.begin(), list.end());
-}
diff --git a/xbmc/input/KeyboardLayout.h b/xbmc/input/KeyboardLayout.h
index d540cb3214..a3f20af2ac 100644
--- a/xbmc/input/KeyboardLayout.h
+++ b/xbmc/input/KeyboardLayout.h
@@ -1,10 +1,4 @@
-/*!
-\file KeyboardLayout.h
-\brief
-*/
-
#pragma once
-
/*
* Copyright (C) 2005-2013 Team XBMC
* http://xbmc.org
@@ -25,46 +19,30 @@
*
*/
-#include <string>
#include <map>
+#include <string>
#include <vector>
-/*!
- \ingroup keyboardlayouts
- \brief
- */
-
class TiXmlElement;
-class CSetting;
class CKeyboardLayout
{
public:
CKeyboardLayout();
- CKeyboardLayout(const std::string &name, const TiXmlElement& element);
- virtual ~CKeyboardLayout(void);
+ virtual ~CKeyboardLayout();
+
+ bool Load(const TiXmlElement* element);
+
const std::string& GetName() const { return m_name; }
- std::string GetCharAt(unsigned int row, unsigned int column, unsigned int modifiers = 0) const;
- enum MODIFIER_KEYS
+ enum ModifierKey
{
- MODIFIER_KEY_NONE = 0x00,
- MODIFIER_KEY_SHIFT = 0x01,
- MODIFIER_KEY_SYMBOL = 0x02
+ ModifierKeyNone = 0x00,
+ ModifierKeyShift = 0x01,
+ ModifierKeySymbol = 0x02
};
- /*! \brief helper to load a keyboard layout
- \param layout the layout to load.
- \return a CKeyboardLayout.
- */
- static CKeyboardLayout Load(const std::string &layout);
-
- /*! \brief helper to list available keyboard layouts
- \return a vector of CKeyboardLayouts with the layout names.
- */
- static std::vector<CKeyboardLayout> LoadLayouts();
-
- static void SettingOptionsKeyboardLayoutsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current, void* data);
+ std::string GetCharAt(unsigned int row, unsigned int column, unsigned int modifiers = 0) const;
private:
static std::vector<std::string> BreakCharacters(const std::string &chars);
@@ -73,5 +51,5 @@ private:
typedef std::map<unsigned int, KeyboardRows> Keyboards;
std::string m_name;
- Keyboards m_keyboards;
+ Keyboards m_keyboards;
};
diff --git a/xbmc/input/KeyboardLayoutManager.cpp b/xbmc/input/KeyboardLayoutManager.cpp
new file mode 100644
index 0000000000..20dd3564d0
--- /dev/null
+++ b/xbmc/input/KeyboardLayoutManager.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <algorithm>
+
+#include "KeyboardLayoutManager.h"
+#include "FileItem.h"
+#include "URL.h"
+#include "filesystem/Directory.h"
+#include "utils/log.h"
+#include "utils/XBMCTinyXML.h"
+
+#define KEYBOARD_LAYOUTS_PATH "special://xbmc/system/keyboardlayouts"
+
+CKeyboardLayoutManager::~CKeyboardLayoutManager()
+{
+ Unload();
+}
+
+CKeyboardLayoutManager& CKeyboardLayoutManager::Get()
+{
+ static CKeyboardLayoutManager s_instance;
+ return s_instance;
+}
+
+bool CKeyboardLayoutManager::Load(const std::string& path /* = "" */)
+{
+ std::string layoutDirectory = path;
+ if (layoutDirectory.empty())
+ layoutDirectory = KEYBOARD_LAYOUTS_PATH;
+
+ if (!XFILE::CDirectory::Exists(layoutDirectory))
+ {
+ CLog::Log(LOGWARNING, "CKeyboardLayoutManager: unable to load keyboard layouts from non-existing directory \"%s\"", layoutDirectory.c_str());
+ return false;
+ }
+
+ CFileItemList layouts;
+ if (!XFILE::CDirectory::GetDirectory(CURL(layoutDirectory), layouts, ".xml") || layouts.IsEmpty())
+ {
+ CLog::Log(LOGWARNING, "CKeyboardLayoutManager: no keyboard layouts found in %s", layoutDirectory.c_str());
+ return false;
+ }
+
+ size_t oldLayoutCount = m_layouts.size();
+ for (int i = 0; i < layouts.Size(); i++)
+ {
+ std::string layoutPath = layouts[i]->GetPath();
+ if (layoutPath.empty())
+ continue;
+
+ CXBMCTinyXML xmlDoc;
+ if (!xmlDoc.LoadFile(layoutPath))
+ {
+ CLog::Log(LOGWARNING, "CKeyboardLayoutManager: unable to open %s", layoutPath.c_str());
+ continue;
+ }
+
+ const TiXmlElement* rootElement = xmlDoc.RootElement();
+ if (rootElement == NULL)
+ {
+ CLog::Log(LOGWARNING, "CKeyboardLayoutManager: missing or invalid XML root element in %s", layoutPath.c_str());
+ continue;
+ }
+
+ if (rootElement->ValueStr() != "keyboardlayouts")
+ {
+ CLog::Log(LOGWARNING, "CKeyboardLayoutManager: unexpected XML root element \"%s\" in %s", rootElement->Value(), layoutPath.c_str());
+ continue;
+ }
+
+ const TiXmlElement* layoutElement = rootElement->FirstChildElement("layout");
+ while (layoutElement != NULL)
+ {
+ CKeyboardLayout layout;
+ if (!layout.Load(layoutElement))
+ CLog::Log(LOGWARNING, "CKeyboardLayoutManager: failed to load %s", layoutPath.c_str());
+ else if (m_layouts.find(layout.GetName()) != m_layouts.end())
+ CLog::Log(LOGWARNING, "CKeyboardLayoutManager: duplicate layout with name \"%s\" in %s", layout.GetName().c_str(), layoutPath.c_str());
+ else
+ m_layouts.insert(std::make_pair(layout.GetName(), layout));
+
+ layoutElement = layoutElement->NextSiblingElement();
+ }
+ }
+
+ return m_layouts.size() > oldLayoutCount;
+}
+
+void CKeyboardLayoutManager::Unload()
+{
+ m_layouts.clear();
+}
+
+bool CKeyboardLayoutManager::GetLayout(const std::string& name, CKeyboardLayout& layout) const
+{
+ if (name.empty())
+ return false;
+
+ KeyboardLayouts::const_iterator it = m_layouts.find(name);
+ if (it == m_layouts.end())
+ return false;
+
+ layout = it->second;
+ return true;
+}
+
+void CKeyboardLayoutManager::SettingOptionsKeyboardLayoutsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current, void* data)
+{
+ for (KeyboardLayouts::const_iterator it = CKeyboardLayoutManager::Get().m_layouts.begin(); it != CKeyboardLayoutManager::Get().m_layouts.end(); ++it)
+ {
+ std::string name = it->second.GetName();
+ list.push_back(make_pair(name, name));
+ }
+
+ std::sort(list.begin(), list.end());
+}
diff --git a/xbmc/input/KeyboardLayoutManager.h b/xbmc/input/KeyboardLayoutManager.h
new file mode 100644
index 0000000000..497c92a598
--- /dev/null
+++ b/xbmc/input/KeyboardLayoutManager.h
@@ -0,0 +1,52 @@
+#pragma once
+/*
+ * Copyright (C) 2015 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <map>
+#include <string>
+
+#include "input/KeyboardLayout.h"
+
+class CSetting;
+
+typedef std::map<std::string, CKeyboardLayout> KeyboardLayouts;
+
+class CKeyboardLayoutManager
+{
+public:
+ virtual ~CKeyboardLayoutManager();
+
+ static CKeyboardLayoutManager& Get();
+
+ bool Load(const std::string& path = "");
+ void Unload();
+
+ const KeyboardLayouts& GetLayouts() const { return m_layouts; }
+ bool GetLayout(const std::string& name, CKeyboardLayout& layout) const;
+
+ static void SettingOptionsKeyboardLayoutsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current, void* data);
+
+private:
+ CKeyboardLayoutManager() { }
+ CKeyboardLayoutManager(const CKeyboardLayoutManager&);
+ CKeyboardLayoutManager const& operator=(CKeyboardLayoutManager const&);
+
+ KeyboardLayouts m_layouts;
+};
diff --git a/xbmc/input/Makefile b/xbmc/input/Makefile
index 2a5c9fa480..fcad66efc6 100644
--- a/xbmc/input/Makefile
+++ b/xbmc/input/Makefile
@@ -1,6 +1,7 @@
SRCS=ButtonTranslator.cpp \
InertialScrollingHandler.cpp \
KeyboardLayout.cpp \
+ KeyboardLayoutManager.cpp \
KeyboardStat.cpp \
MouseStat.cpp \
SDLJoystick.cpp \
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index 871de64bab..34e02c6c32 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -36,7 +36,7 @@
#include "guilib/GUIFontManager.h"
#include "guilib/LocalizeStrings.h"
#include "guilib/StereoscopicsManager.h"
-#include "input/KeyboardLayout.h"
+#include "input/KeyboardLayoutManager.h"
#if defined(TARGET_POSIX)
#include "linux/LinuxTimezone.h"
#endif // defined(TARGET_POSIX)
@@ -608,7 +608,7 @@ void CSettings::InitializeOptionFillers()
m_settingsManager->RegisterSettingOptionsFiller("timezones", CLinuxTimezone::SettingOptionsTimezonesFiller);
#endif
m_settingsManager->RegisterSettingOptionsFiller("verticalsyncs", CDisplaySettings::SettingOptionsVerticalSyncsFiller);
- m_settingsManager->RegisterSettingOptionsFiller("keyboardlayouts", CKeyboardLayout::SettingOptionsKeyboardLayoutsFiller);
+ m_settingsManager->RegisterSettingOptionsFiller("keyboardlayouts", CKeyboardLayoutManager::SettingOptionsKeyboardLayoutsFiller);
m_settingsManager->RegisterSettingOptionsFiller("loggingcomponents", CAdvancedSettings::SettingOptionsLoggingComponentsFiller);
}