diff options
-rw-r--r-- | Kodi.xcodeproj/project.pbxproj | 10 | ||||
-rw-r--r-- | project/VS2010Express/XBMC.vcxproj | 4 | ||||
-rw-r--r-- | project/VS2010Express/XBMC.vcxproj.filters | 8 | ||||
-rw-r--r-- | system/keyboardlayouts/keyboardlayouts.xml (renamed from system/keyboardlayouts.xml) | 0 | ||||
-rw-r--r-- | xbmc/Application.cpp | 8 | ||||
-rw-r--r-- | xbmc/dialogs/GUIDialogKeyboardGeneric.cpp | 24 | ||||
-rw-r--r-- | xbmc/input/KeyboardLayout.cpp | 100 | ||||
-rw-r--r-- | xbmc/input/KeyboardLayout.h | 44 | ||||
-rw-r--r-- | xbmc/input/KeyboardLayoutManager.cpp | 134 | ||||
-rw-r--r-- | xbmc/input/KeyboardLayoutManager.h | 52 | ||||
-rw-r--r-- | xbmc/input/Makefile | 1 | ||||
-rw-r--r-- | xbmc/settings/Settings.cpp | 4 |
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 ¤t, 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 ¤t, 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 ¤t, 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 ¤t, 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); } |