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.
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"
24 using namespace KODI::MESSAGING
;
25 using KODI::UTILITY::CDigest
;
27 CGUIDialogGamepad::CGUIDialogGamepad(void)
28 : CGUIDialogBoxBase(WINDOW_DIALOG_GAMEPAD
, "DialogConfirm.xml")
32 m_bUserInputCleanup
= true;
33 m_bHideInputChars
= true;
34 m_cHideInputChar
= '*';
37 CGUIDialogGamepad::~CGUIDialogGamepad(void) = default;
39 void CGUIDialogGamepad::OnInitWindow()
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;
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;
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
)});
96 else if (action
.GetButtonCode() == KEY_BUTTON_BACK
|| action
.GetID() == ACTION_PREVIOUS_MENU
|| action
.GetID() == ACTION_NAV_BACK
)
101 m_bHideInputChars
= true;
105 else if (action
.GetButtonCode() == KEY_BUTTON_START
|| action
.GetID() == ACTION_SELECT_ITEM
)
107 m_bConfirmed
= false;
110 std::string md5pword2
= CDigest::Calculate(CDigest::Type::MD5
, m_strUserInput
);
112 if (!StringUtils::EqualsNoCase(m_strPassword
, md5pword2
))
114 // incorrect password entered
117 // don't clean up if the calling code wants the bad user input
118 if (m_bUserInputCleanup
)
121 m_bUserInputCleanup
= true;
123 m_bHideInputChars
= true;
128 // correct password entered
132 m_bHideInputChars
= true;
136 else if (action
.GetID() >= REMOTE_0
&& action
.GetID() <= REMOTE_9
)
138 return true; // unhandled
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;
154 m_cHideInputChar
= g_localizeStrings
.Get(12322).c_str()[0];
155 CGUIDialog::OnMessage(message
);
160 case GUI_MSG_CLICKED
:
162 m_bConfirmed
= false;
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
185 if (strUserInput
.empty())
190 // We should have a string to return
191 aTextString
= strUserInput
;
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
209 if (strUserInput
.empty())
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
221 // password entry and re-entry succeeded
222 strNewPassword
= strUserInput
;
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
;
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
249 if (strPassTemp
.empty())
253 // user must have entered an incorrect password
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
});
280 pDialog
->SetHeading(CVariant
{atoi(dlgHeading
.c_str())});
282 if (!StringUtils::IsNaturalNumber(dlgLine0
))
283 pDialog
->SetLine(0, CVariant
{dlgLine0
});
285 pDialog
->SetLine(0, CVariant
{atoi(dlgLine0
.c_str())});
287 if (!StringUtils::IsNaturalNumber(dlgLine1
))
288 pDialog
->SetLine(1, CVariant
{dlgLine1
});
290 pDialog
->SetLine(1, CVariant
{atoi(dlgLine1
.c_str())});
292 if (!StringUtils::IsNaturalNumber(dlgLine2
))
293 pDialog
->SetLine(2, CVariant
{dlgLine2
});
295 pDialog
->SetLine(2, CVariant
{atoi(dlgLine2
.c_str())});
297 CGUIComponent
* gui
= CServiceBroker::GetGUI();
299 gui
->GetAudioManager().Enable(false); // don't do sounds during pwd input
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
318 // user entered correct password
322 bool CGUIDialogGamepad::IsCanceled() const