diff options
Diffstat (limited to 'xbmc/dialogs/GUIDialogGamepad.cpp')
-rw-r--r-- | xbmc/dialogs/GUIDialogGamepad.cpp | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/xbmc/dialogs/GUIDialogGamepad.cpp b/xbmc/dialogs/GUIDialogGamepad.cpp new file mode 100644 index 0000000..07f5809 --- /dev/null +++ b/xbmc/dialogs/GUIDialogGamepad.cpp @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIDialogGamepad.h" + +#include "ServiceBroker.h" +#include "guilib/GUIAudioManager.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "input/Key.h" +#include "messaging/helpers/DialogOKHelper.h" +#include "utils/Digest.h" +#include "utils/StringUtils.h" +#include "utils/Variant.h" + +#include <utility> + +using namespace KODI::MESSAGING; +using KODI::UTILITY::CDigest; + +CGUIDialogGamepad::CGUIDialogGamepad(void) + : CGUIDialogBoxBase(WINDOW_DIALOG_GAMEPAD, "DialogConfirm.xml") +{ + m_bCanceled = false; + m_iRetries = 0; + m_bUserInputCleanup = true; + m_bHideInputChars = true; + m_cHideInputChar = '*'; +} + +CGUIDialogGamepad::~CGUIDialogGamepad(void) = default; + +void CGUIDialogGamepad::OnInitWindow() +{ + // hide all controls + for (int i = 0; i < DIALOG_MAX_CHOICES; ++i) + SET_CONTROL_HIDDEN(CONTROL_CHOICES_START + i); + SET_CONTROL_HIDDEN(CONTROL_PROGRESS_BAR); + + CGUIDialogBoxBase::OnInitWindow(); +} + +bool CGUIDialogGamepad::OnAction(const CAction &action) +{ + if ((action.GetButtonCode() >= KEY_BUTTON_A && + action.GetButtonCode() <= KEY_BUTTON_RIGHT_TRIGGER) || + (action.GetButtonCode() >= KEY_BUTTON_DPAD_UP && + action.GetButtonCode() <= KEY_BUTTON_DPAD_RIGHT) || + (action.GetID() >= ACTION_MOVE_LEFT && + action.GetID() <= ACTION_MOVE_DOWN) || + action.GetID() == ACTION_PLAYER_PLAY + ) + { + switch (action.GetButtonCode()) + { + case KEY_BUTTON_A : m_strUserInput += "A"; break; + case KEY_BUTTON_B : m_strUserInput += "B"; break; + case KEY_BUTTON_X : m_strUserInput += "X"; break; + case KEY_BUTTON_Y : m_strUserInput += "Y"; break; + case KEY_BUTTON_BLACK : m_strUserInput += "K"; break; + case KEY_BUTTON_WHITE : m_strUserInput += "W"; break; + case KEY_BUTTON_LEFT_TRIGGER : m_strUserInput += "("; break; + case KEY_BUTTON_RIGHT_TRIGGER : m_strUserInput += ")"; break; + case KEY_BUTTON_DPAD_UP : m_strUserInput += "U"; break; + case KEY_BUTTON_DPAD_DOWN : m_strUserInput += "D"; break; + case KEY_BUTTON_DPAD_LEFT : m_strUserInput += "L"; break; + case KEY_BUTTON_DPAD_RIGHT : m_strUserInput += "R"; break; + default: + switch (action.GetID()) + { + case ACTION_MOVE_LEFT: m_strUserInput += "L"; break; + case ACTION_MOVE_RIGHT: m_strUserInput += "R"; break; + case ACTION_MOVE_UP: m_strUserInput += "U"; break; + case ACTION_MOVE_DOWN: m_strUserInput += "D"; break; + case ACTION_PLAYER_PLAY: m_strUserInput += "P"; break; + default: + return true; + } + break; + } + + std::string strHiddenInput(m_strUserInput); + for (int i = 0; i < (int)strHiddenInput.size(); i++) + { + strHiddenInput[i] = m_cHideInputChar; + } + SetLine(2, CVariant{std::move(strHiddenInput)}); + return true; + } + else if (action.GetButtonCode() == KEY_BUTTON_BACK || action.GetID() == ACTION_PREVIOUS_MENU || action.GetID() == ACTION_NAV_BACK) + { + m_bConfirmed = false; + m_bCanceled = true; + m_strUserInput = ""; + m_bHideInputChars = true; + Close(); + return true; + } + else if (action.GetButtonCode() == KEY_BUTTON_START || action.GetID() == ACTION_SELECT_ITEM) + { + m_bConfirmed = false; + m_bCanceled = false; + + std::string md5pword2 = CDigest::Calculate(CDigest::Type::MD5, m_strUserInput); + + if (!StringUtils::EqualsNoCase(m_strPassword, md5pword2)) + { + // incorrect password entered + m_iRetries--; + + // don't clean up if the calling code wants the bad user input + if (m_bUserInputCleanup) + m_strUserInput = ""; + else + m_bUserInputCleanup = true; + + m_bHideInputChars = true; + Close(); + return true; + } + + // correct password entered + m_bConfirmed = true; + m_iRetries = 0; + m_strUserInput = ""; + m_bHideInputChars = true; + Close(); + return true; + } + else if (action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) + { + return true; // unhandled + } + else + { + return CGUIDialog::OnAction(action); + } +} + +bool CGUIDialogGamepad::OnMessage(CGUIMessage& message) +{ + switch ( message.GetMessage() ) + { + case GUI_MSG_WINDOW_INIT: + { + m_bConfirmed = false; + m_bCanceled = false; + m_cHideInputChar = g_localizeStrings.Get(12322).c_str()[0]; + CGUIDialog::OnMessage(message); + return true; + } + break; + + case GUI_MSG_CLICKED: + { + m_bConfirmed = false; + m_bCanceled = false; + } + break; + } + return CGUIDialogBoxBase::OnMessage(message); +} + +// \brief Show gamepad keypad and replace aTextString with user input. +// \param aTextString String to preload into the keyboard accumulator. Overwritten with user input if return=true. +// \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer. +// \param bHideUserInput Masks user input as asterisks if set as true. Currently not yet implemented. +// \return true if successful display and user input. false if unsuccessful display, no user input, or canceled editing. +bool CGUIDialogGamepad::ShowAndGetInput(std::string& aTextString, const std::string &dlgHeading, bool bHideUserInput) +{ + // Prompt user for input + std::string strUserInput; + if (ShowAndVerifyInput(strUserInput, dlgHeading, aTextString, "", "", true, bHideUserInput)) + { + // user entry was blank + return false; + } + + if (strUserInput.empty()) + // user canceled out + return false; + + + // We should have a string to return + aTextString = strUserInput; + return true; +} + +// \brief Show gamepad keypad twice to get and confirm a user-entered password string. +// \param strNewPassword String to preload into the keyboard accumulator. Overwritten with user input if return=true. +// \return true if successful display and user input entry/re-entry. false if unsuccessful display, no user input, or canceled editing. +bool CGUIDialogGamepad::ShowAndVerifyNewPassword(std::string& strNewPassword) +{ + // Prompt user for password input + std::string strUserInput; + if (ShowAndVerifyInput(strUserInput, "12340", "12330", "12331", "", true, true)) + { + //! @todo Show error to user saying the password entry was blank + HELPERS::ShowOKDialogText(CVariant{12357}, CVariant{12358}); // Password is empty/blank + return false; + } + + if (strUserInput.empty()) + // user canceled out + return false; + + // Prompt again for password input, this time sending previous input as the password to verify + if (!ShowAndVerifyInput(strUserInput, "12341", "12330", "12331", "", false, true)) + { + //! @todo Show error to user saying the password re-entry failed + HELPERS::ShowOKDialogText(CVariant{12357}, CVariant{12344}); // Password do not match + return false; + } + + // password entry and re-entry succeeded + strNewPassword = strUserInput; + return true; +} + +// \brief Show gamepad keypad and verify user input against strPassword. +// \param strPassword Value to compare against user input. +// \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer. +// \param iRetries If greater than 0, shows "Incorrect password, %d retries left" on dialog line 2, else line 2 is blank. +// \return 0 if successful display and user input. 1 if unsuccessful input. -1 if no user input or canceled editing. +int CGUIDialogGamepad::ShowAndVerifyPassword(std::string& strPassword, const std::string& dlgHeading, int iRetries) +{ + std::string strLine2; + if (0 < iRetries) + { + // Show a string telling user they have iRetries retries left + strLine2 = StringUtils::Format("{} {} {}", g_localizeStrings.Get(12342), iRetries, + g_localizeStrings.Get(12343)); + } + + // make a copy of strPassword to prevent from overwriting it later + std::string strPassTemp = strPassword; + if (ShowAndVerifyInput(strPassTemp, dlgHeading, g_localizeStrings.Get(12330), g_localizeStrings.Get(12331), strLine2, true, true)) + { + // user entered correct password + return 0; + } + + if (strPassTemp.empty()) + // user canceled out + return -1; + + // user must have entered an incorrect password + return 1; +} + +// \brief Show gamepad keypad and verify user input against strToVerify. +// \param strToVerify Value to compare against user input. +// \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer. +// \param dlgLine0 String shown on dialog line 0. Converts to localized string if contains a positive integer. +// \param dlgLine1 String shown on dialog line 1. Converts to localized string if contains a positive integer. +// \param dlgLine2 String shown on dialog line 2. Converts to localized string if contains a positive integer. +// \param bGetUserInput If set as true and return=true, strToVerify is overwritten with user input string. +// \param bHideInputChars Masks user input as asterisks if set as true. Currently not yet implemented. +// \return true if successful display and user input. false if unsuccessful display, no user input, or canceled editing. +bool CGUIDialogGamepad::ShowAndVerifyInput(std::string& strToVerify, const std::string& dlgHeading, + const std::string& dlgLine0, const std::string& dlgLine1, + const std::string& dlgLine2, bool bGetUserInput, bool bHideInputChars) +{ + // Prompt user for password input + CGUIDialogGamepad *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogGamepad>(WINDOW_DIALOG_GAMEPAD); + pDialog->m_strPassword = strToVerify; + pDialog->m_bUserInputCleanup = !bGetUserInput; + pDialog->m_bHideInputChars = bHideInputChars; + + // HACK: This won't work if the label specified is actually a positive numeric value, but that's very unlikely + if (!StringUtils::IsNaturalNumber(dlgHeading)) + pDialog->SetHeading(CVariant{dlgHeading}); + else + pDialog->SetHeading(CVariant{atoi(dlgHeading.c_str())}); + + if (!StringUtils::IsNaturalNumber(dlgLine0)) + pDialog->SetLine(0, CVariant{dlgLine0}); + else + pDialog->SetLine(0, CVariant{atoi(dlgLine0.c_str())}); + + if (!StringUtils::IsNaturalNumber(dlgLine1)) + pDialog->SetLine(1, CVariant{dlgLine1}); + else + pDialog->SetLine(1, CVariant{atoi(dlgLine1.c_str())}); + + if (!StringUtils::IsNaturalNumber(dlgLine2)) + pDialog->SetLine(2, CVariant{dlgLine2}); + else + pDialog->SetLine(2, CVariant{atoi(dlgLine2.c_str())}); + + CGUIComponent* gui = CServiceBroker::GetGUI(); + if (gui) + gui->GetAudioManager().Enable(false); // don't do sounds during pwd input + + pDialog->Open(); + + if (gui) + gui->GetAudioManager().Enable(true); + + if (bGetUserInput && !pDialog->IsCanceled()) + { + strToVerify = CDigest::Calculate(CDigest::Type::MD5, pDialog->m_strUserInput); + pDialog->m_strUserInput = ""; + } + + if (!pDialog->IsConfirmed() || pDialog->IsCanceled()) + { + // user canceled out or entered an incorrect password + return false; + } + + // user entered correct password + return true; +} + +bool CGUIDialogGamepad::IsCanceled() const +{ + return m_bCanceled; +} + |