Merge pull request #24470 from fuzzard/release_20.3
[xbmc.git] / xbmc / dialogs / GUIDialogGamepad.cpp
blob07f58097f28749cadd29afba967fef2fb9408ae2
1 /*
2 * Copyright (C) 2005-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 "GUIDialogGamepad.h"
11 #include "ServiceBroker.h"
12 #include "guilib/GUIAudioManager.h"
13 #include "guilib/GUIComponent.h"
14 #include "guilib/GUIWindowManager.h"
15 #include "guilib/LocalizeStrings.h"
16 #include "input/Key.h"
17 #include "messaging/helpers/DialogOKHelper.h"
18 #include "utils/Digest.h"
19 #include "utils/StringUtils.h"
20 #include "utils/Variant.h"
22 #include <utility>
24 using namespace KODI::MESSAGING;
25 using KODI::UTILITY::CDigest;
27 CGUIDialogGamepad::CGUIDialogGamepad(void)
28 : CGUIDialogBoxBase(WINDOW_DIALOG_GAMEPAD, "DialogConfirm.xml")
30 m_bCanceled = false;
31 m_iRetries = 0;
32 m_bUserInputCleanup = true;
33 m_bHideInputChars = true;
34 m_cHideInputChar = '*';
37 CGUIDialogGamepad::~CGUIDialogGamepad(void) = default;
39 void CGUIDialogGamepad::OnInitWindow()
41 // hide all controls
42 for (int i = 0; i < DIALOG_MAX_CHOICES; ++i)
43 SET_CONTROL_HIDDEN(CONTROL_CHOICES_START + i);
44 SET_CONTROL_HIDDEN(CONTROL_PROGRESS_BAR);
46 CGUIDialogBoxBase::OnInitWindow();
49 bool CGUIDialogGamepad::OnAction(const CAction &action)
51 if ((action.GetButtonCode() >= KEY_BUTTON_A &&
52 action.GetButtonCode() <= KEY_BUTTON_RIGHT_TRIGGER) ||
53 (action.GetButtonCode() >= KEY_BUTTON_DPAD_UP &&
54 action.GetButtonCode() <= KEY_BUTTON_DPAD_RIGHT) ||
55 (action.GetID() >= ACTION_MOVE_LEFT &&
56 action.GetID() <= ACTION_MOVE_DOWN) ||
57 action.GetID() == ACTION_PLAYER_PLAY
60 switch (action.GetButtonCode())
62 case KEY_BUTTON_A : m_strUserInput += "A"; break;
63 case KEY_BUTTON_B : m_strUserInput += "B"; break;
64 case KEY_BUTTON_X : m_strUserInput += "X"; break;
65 case KEY_BUTTON_Y : m_strUserInput += "Y"; break;
66 case KEY_BUTTON_BLACK : m_strUserInput += "K"; break;
67 case KEY_BUTTON_WHITE : m_strUserInput += "W"; break;
68 case KEY_BUTTON_LEFT_TRIGGER : m_strUserInput += "("; break;
69 case KEY_BUTTON_RIGHT_TRIGGER : m_strUserInput += ")"; break;
70 case KEY_BUTTON_DPAD_UP : m_strUserInput += "U"; break;
71 case KEY_BUTTON_DPAD_DOWN : m_strUserInput += "D"; break;
72 case KEY_BUTTON_DPAD_LEFT : m_strUserInput += "L"; break;
73 case KEY_BUTTON_DPAD_RIGHT : m_strUserInput += "R"; break;
74 default:
75 switch (action.GetID())
77 case ACTION_MOVE_LEFT: m_strUserInput += "L"; break;
78 case ACTION_MOVE_RIGHT: m_strUserInput += "R"; break;
79 case ACTION_MOVE_UP: m_strUserInput += "U"; break;
80 case ACTION_MOVE_DOWN: m_strUserInput += "D"; break;
81 case ACTION_PLAYER_PLAY: m_strUserInput += "P"; break;
82 default:
83 return true;
85 break;
88 std::string strHiddenInput(m_strUserInput);
89 for (int i = 0; i < (int)strHiddenInput.size(); i++)
91 strHiddenInput[i] = m_cHideInputChar;
93 SetLine(2, CVariant{std::move(strHiddenInput)});
94 return true;
96 else if (action.GetButtonCode() == KEY_BUTTON_BACK || action.GetID() == ACTION_PREVIOUS_MENU || action.GetID() == ACTION_NAV_BACK)
98 m_bConfirmed = false;
99 m_bCanceled = true;
100 m_strUserInput = "";
101 m_bHideInputChars = true;
102 Close();
103 return true;
105 else if (action.GetButtonCode() == KEY_BUTTON_START || action.GetID() == ACTION_SELECT_ITEM)
107 m_bConfirmed = false;
108 m_bCanceled = false;
110 std::string md5pword2 = CDigest::Calculate(CDigest::Type::MD5, m_strUserInput);
112 if (!StringUtils::EqualsNoCase(m_strPassword, md5pword2))
114 // incorrect password entered
115 m_iRetries--;
117 // don't clean up if the calling code wants the bad user input
118 if (m_bUserInputCleanup)
119 m_strUserInput = "";
120 else
121 m_bUserInputCleanup = true;
123 m_bHideInputChars = true;
124 Close();
125 return true;
128 // correct password entered
129 m_bConfirmed = true;
130 m_iRetries = 0;
131 m_strUserInput = "";
132 m_bHideInputChars = true;
133 Close();
134 return true;
136 else if (action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9)
138 return true; // unhandled
140 else
142 return CGUIDialog::OnAction(action);
146 bool CGUIDialogGamepad::OnMessage(CGUIMessage& message)
148 switch ( message.GetMessage() )
150 case GUI_MSG_WINDOW_INIT:
152 m_bConfirmed = false;
153 m_bCanceled = false;
154 m_cHideInputChar = g_localizeStrings.Get(12322).c_str()[0];
155 CGUIDialog::OnMessage(message);
156 return true;
158 break;
160 case GUI_MSG_CLICKED:
162 m_bConfirmed = false;
163 m_bCanceled = false;
165 break;
167 return CGUIDialogBoxBase::OnMessage(message);
170 // \brief Show gamepad keypad and replace aTextString with user input.
171 // \param aTextString String to preload into the keyboard accumulator. Overwritten with user input if return=true.
172 // \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
173 // \param bHideUserInput Masks user input as asterisks if set as true. Currently not yet implemented.
174 // \return true if successful display and user input. false if unsuccessful display, no user input, or canceled editing.
175 bool CGUIDialogGamepad::ShowAndGetInput(std::string& aTextString, const std::string &dlgHeading, bool bHideUserInput)
177 // Prompt user for input
178 std::string strUserInput;
179 if (ShowAndVerifyInput(strUserInput, dlgHeading, aTextString, "", "", true, bHideUserInput))
181 // user entry was blank
182 return false;
185 if (strUserInput.empty())
186 // user canceled out
187 return false;
190 // We should have a string to return
191 aTextString = strUserInput;
192 return true;
195 // \brief Show gamepad keypad twice to get and confirm a user-entered password string.
196 // \param strNewPassword String to preload into the keyboard accumulator. Overwritten with user input if return=true.
197 // \return true if successful display and user input entry/re-entry. false if unsuccessful display, no user input, or canceled editing.
198 bool CGUIDialogGamepad::ShowAndVerifyNewPassword(std::string& strNewPassword)
200 // Prompt user for password input
201 std::string strUserInput;
202 if (ShowAndVerifyInput(strUserInput, "12340", "12330", "12331", "", true, true))
204 //! @todo Show error to user saying the password entry was blank
205 HELPERS::ShowOKDialogText(CVariant{12357}, CVariant{12358}); // Password is empty/blank
206 return false;
209 if (strUserInput.empty())
210 // user canceled out
211 return false;
213 // Prompt again for password input, this time sending previous input as the password to verify
214 if (!ShowAndVerifyInput(strUserInput, "12341", "12330", "12331", "", false, true))
216 //! @todo Show error to user saying the password re-entry failed
217 HELPERS::ShowOKDialogText(CVariant{12357}, CVariant{12344}); // Password do not match
218 return false;
221 // password entry and re-entry succeeded
222 strNewPassword = strUserInput;
223 return true;
226 // \brief Show gamepad keypad and verify user input against strPassword.
227 // \param strPassword Value to compare against user input.
228 // \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
229 // \param iRetries If greater than 0, shows "Incorrect password, %d retries left" on dialog line 2, else line 2 is blank.
230 // \return 0 if successful display and user input. 1 if unsuccessful input. -1 if no user input or canceled editing.
231 int CGUIDialogGamepad::ShowAndVerifyPassword(std::string& strPassword, const std::string& dlgHeading, int iRetries)
233 std::string strLine2;
234 if (0 < iRetries)
236 // Show a string telling user they have iRetries retries left
237 strLine2 = StringUtils::Format("{} {} {}", g_localizeStrings.Get(12342), iRetries,
238 g_localizeStrings.Get(12343));
241 // make a copy of strPassword to prevent from overwriting it later
242 std::string strPassTemp = strPassword;
243 if (ShowAndVerifyInput(strPassTemp, dlgHeading, g_localizeStrings.Get(12330), g_localizeStrings.Get(12331), strLine2, true, true))
245 // user entered correct password
246 return 0;
249 if (strPassTemp.empty())
250 // user canceled out
251 return -1;
253 // user must have entered an incorrect password
254 return 1;
257 // \brief Show gamepad keypad and verify user input against strToVerify.
258 // \param strToVerify Value to compare against user input.
259 // \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
260 // \param dlgLine0 String shown on dialog line 0. Converts to localized string if contains a positive integer.
261 // \param dlgLine1 String shown on dialog line 1. Converts to localized string if contains a positive integer.
262 // \param dlgLine2 String shown on dialog line 2. Converts to localized string if contains a positive integer.
263 // \param bGetUserInput If set as true and return=true, strToVerify is overwritten with user input string.
264 // \param bHideInputChars Masks user input as asterisks if set as true. Currently not yet implemented.
265 // \return true if successful display and user input. false if unsuccessful display, no user input, or canceled editing.
266 bool CGUIDialogGamepad::ShowAndVerifyInput(std::string& strToVerify, const std::string& dlgHeading,
267 const std::string& dlgLine0, const std::string& dlgLine1,
268 const std::string& dlgLine2, bool bGetUserInput, bool bHideInputChars)
270 // Prompt user for password input
271 CGUIDialogGamepad *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogGamepad>(WINDOW_DIALOG_GAMEPAD);
272 pDialog->m_strPassword = strToVerify;
273 pDialog->m_bUserInputCleanup = !bGetUserInput;
274 pDialog->m_bHideInputChars = bHideInputChars;
276 // HACK: This won't work if the label specified is actually a positive numeric value, but that's very unlikely
277 if (!StringUtils::IsNaturalNumber(dlgHeading))
278 pDialog->SetHeading(CVariant{dlgHeading});
279 else
280 pDialog->SetHeading(CVariant{atoi(dlgHeading.c_str())});
282 if (!StringUtils::IsNaturalNumber(dlgLine0))
283 pDialog->SetLine(0, CVariant{dlgLine0});
284 else
285 pDialog->SetLine(0, CVariant{atoi(dlgLine0.c_str())});
287 if (!StringUtils::IsNaturalNumber(dlgLine1))
288 pDialog->SetLine(1, CVariant{dlgLine1});
289 else
290 pDialog->SetLine(1, CVariant{atoi(dlgLine1.c_str())});
292 if (!StringUtils::IsNaturalNumber(dlgLine2))
293 pDialog->SetLine(2, CVariant{dlgLine2});
294 else
295 pDialog->SetLine(2, CVariant{atoi(dlgLine2.c_str())});
297 CGUIComponent* gui = CServiceBroker::GetGUI();
298 if (gui)
299 gui->GetAudioManager().Enable(false); // don't do sounds during pwd input
301 pDialog->Open();
303 if (gui)
304 gui->GetAudioManager().Enable(true);
306 if (bGetUserInput && !pDialog->IsCanceled())
308 strToVerify = CDigest::Calculate(CDigest::Type::MD5, pDialog->m_strUserInput);
309 pDialog->m_strUserInput = "";
312 if (!pDialog->IsConfirmed() || pDialog->IsCanceled())
314 // user canceled out or entered an incorrect password
315 return false;
318 // user entered correct password
319 return true;
322 bool CGUIDialogGamepad::IsCanceled() const
324 return m_bCanceled;