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/actions/Action.h"
17 #include "input/actions/ActionIDs.h"
18 #include "input/keyboard/KeyIDs.h"
19 #include "messaging/helpers/DialogOKHelper.h"
20 #include "utils/Digest.h"
21 #include "utils/StringUtils.h"
22 #include "utils/Variant.h"
26 using namespace KODI::MESSAGING
;
27 using KODI::UTILITY::CDigest
;
29 CGUIDialogGamepad::CGUIDialogGamepad(void)
30 : CGUIDialogBoxBase(WINDOW_DIALOG_GAMEPAD
, "DialogConfirm.xml")
34 m_bUserInputCleanup
= true;
35 m_bHideInputChars
= true;
36 m_cHideInputChar
= '*';
39 CGUIDialogGamepad::~CGUIDialogGamepad(void) = default;
41 void CGUIDialogGamepad::OnInitWindow()
44 for (int i
= 0; i
< DIALOG_MAX_CHOICES
; ++i
)
45 SET_CONTROL_HIDDEN(CONTROL_CHOICES_START
+ i
);
46 SET_CONTROL_HIDDEN(CONTROL_PROGRESS_BAR
);
48 CGUIDialogBoxBase::OnInitWindow();
51 bool CGUIDialogGamepad::OnAction(const CAction
&action
)
53 if ((action
.GetButtonCode() >= KEY_BUTTON_A
&&
54 action
.GetButtonCode() <= KEY_BUTTON_RIGHT_TRIGGER
) ||
55 (action
.GetButtonCode() >= KEY_BUTTON_DPAD_UP
&&
56 action
.GetButtonCode() <= KEY_BUTTON_DPAD_RIGHT
) ||
57 (action
.GetID() >= ACTION_MOVE_LEFT
&&
58 action
.GetID() <= ACTION_MOVE_DOWN
) ||
59 action
.GetID() == ACTION_PLAYER_PLAY
62 switch (action
.GetButtonCode())
64 case KEY_BUTTON_A
: m_strUserInput
+= "A"; break;
65 case KEY_BUTTON_B
: m_strUserInput
+= "B"; break;
66 case KEY_BUTTON_X
: m_strUserInput
+= "X"; break;
67 case KEY_BUTTON_Y
: m_strUserInput
+= "Y"; break;
68 case KEY_BUTTON_BLACK
: m_strUserInput
+= "K"; break;
69 case KEY_BUTTON_WHITE
: m_strUserInput
+= "W"; break;
70 case KEY_BUTTON_LEFT_TRIGGER
: m_strUserInput
+= "("; break;
71 case KEY_BUTTON_RIGHT_TRIGGER
: m_strUserInput
+= ")"; break;
72 case KEY_BUTTON_DPAD_UP
: m_strUserInput
+= "U"; break;
73 case KEY_BUTTON_DPAD_DOWN
: m_strUserInput
+= "D"; break;
74 case KEY_BUTTON_DPAD_LEFT
: m_strUserInput
+= "L"; break;
75 case KEY_BUTTON_DPAD_RIGHT
: m_strUserInput
+= "R"; break;
77 switch (action
.GetID())
79 case ACTION_MOVE_LEFT
: m_strUserInput
+= "L"; break;
80 case ACTION_MOVE_RIGHT
: m_strUserInput
+= "R"; break;
81 case ACTION_MOVE_UP
: m_strUserInput
+= "U"; break;
82 case ACTION_MOVE_DOWN
: m_strUserInput
+= "D"; break;
83 case ACTION_PLAYER_PLAY
: m_strUserInput
+= "P"; break;
90 std::string
strHiddenInput(m_strUserInput
);
91 for (int i
= 0; i
< (int)strHiddenInput
.size(); i
++)
93 strHiddenInput
[i
] = m_cHideInputChar
;
95 SetLine(2, CVariant
{std::move(strHiddenInput
)});
98 else if (action
.GetButtonCode() == KEY_BUTTON_BACK
|| action
.GetID() == ACTION_PREVIOUS_MENU
|| action
.GetID() == ACTION_NAV_BACK
)
100 m_bConfirmed
= false;
103 m_bHideInputChars
= true;
107 else if (action
.GetButtonCode() == KEY_BUTTON_START
|| action
.GetID() == ACTION_SELECT_ITEM
)
109 m_bConfirmed
= false;
112 std::string md5pword2
= CDigest::Calculate(CDigest::Type::MD5
, m_strUserInput
);
114 if (!StringUtils::EqualsNoCase(m_strPassword
, md5pword2
))
116 // incorrect password entered
119 // don't clean up if the calling code wants the bad user input
120 if (m_bUserInputCleanup
)
123 m_bUserInputCleanup
= true;
125 m_bHideInputChars
= true;
130 // correct password entered
134 m_bHideInputChars
= true;
138 else if (action
.GetID() >= REMOTE_0
&& action
.GetID() <= REMOTE_9
)
140 return true; // unhandled
144 return CGUIDialog::OnAction(action
);
148 bool CGUIDialogGamepad::OnMessage(CGUIMessage
& message
)
150 switch ( message
.GetMessage() )
152 case GUI_MSG_WINDOW_INIT
:
154 m_bConfirmed
= false;
156 m_cHideInputChar
= g_localizeStrings
.Get(12322).c_str()[0];
157 CGUIDialog::OnMessage(message
);
162 case GUI_MSG_CLICKED
:
164 m_bConfirmed
= false;
169 return CGUIDialogBoxBase::OnMessage(message
);
172 // \brief Show gamepad keypad and replace aTextString with user input.
173 // \param aTextString String to preload into the keyboard accumulator. Overwritten with user input if return=true.
174 // \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
175 // \param bHideUserInput Masks user input as asterisks if set as true. Currently not yet implemented.
176 // \return true if successful display and user input. false if unsuccessful display, no user input, or canceled editing.
177 bool CGUIDialogGamepad::ShowAndGetInput(std::string
& aTextString
, const std::string
&dlgHeading
, bool bHideUserInput
)
179 // Prompt user for input
180 std::string strUserInput
;
181 if (ShowAndVerifyInput(strUserInput
, dlgHeading
, aTextString
, "", "", true, bHideUserInput
))
183 // user entry was blank
187 if (strUserInput
.empty())
192 // We should have a string to return
193 aTextString
= strUserInput
;
197 // \brief Show gamepad keypad twice to get and confirm a user-entered password string.
198 // \param strNewPassword String to preload into the keyboard accumulator. Overwritten with user input if return=true.
199 // \return true if successful display and user input entry/re-entry. false if unsuccessful display, no user input, or canceled editing.
200 bool CGUIDialogGamepad::ShowAndVerifyNewPassword(std::string
& strNewPassword
)
202 // Prompt user for password input
203 std::string strUserInput
;
204 if (ShowAndVerifyInput(strUserInput
, "12340", "12330", "12331", "", true, true))
206 //! @todo Show error to user saying the password entry was blank
207 HELPERS::ShowOKDialogText(CVariant
{12357}, CVariant
{12358}); // Password is empty/blank
211 if (strUserInput
.empty())
215 // Prompt again for password input, this time sending previous input as the password to verify
216 if (!ShowAndVerifyInput(strUserInput
, "12341", "12330", "12331", "", false, true))
218 //! @todo Show error to user saying the password re-entry failed
219 HELPERS::ShowOKDialogText(CVariant
{12357}, CVariant
{12344}); // Password do not match
223 // password entry and re-entry succeeded
224 strNewPassword
= strUserInput
;
228 // \brief Show gamepad keypad and verify user input against strPassword.
229 // \param strPassword Value to compare against user input.
230 // \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
231 // \param iRetries If greater than 0, shows "Incorrect password, %d retries left" on dialog line 2, else line 2 is blank.
232 // \return 0 if successful display and user input. 1 if unsuccessful input. -1 if no user input or canceled editing.
233 int CGUIDialogGamepad::ShowAndVerifyPassword(std::string
& strPassword
, const std::string
& dlgHeading
, int iRetries
)
235 std::string strLine2
;
238 // Show a string telling user they have iRetries retries left
239 strLine2
= StringUtils::Format("{} {} {}", g_localizeStrings
.Get(12342), iRetries
,
240 g_localizeStrings
.Get(12343));
243 // make a copy of strPassword to prevent from overwriting it later
244 std::string strPassTemp
= strPassword
;
245 if (ShowAndVerifyInput(strPassTemp
, dlgHeading
, g_localizeStrings
.Get(12330), g_localizeStrings
.Get(12331), strLine2
, true, true))
247 // user entered correct password
251 if (strPassTemp
.empty())
255 // user must have entered an incorrect password
259 // \brief Show gamepad keypad and verify user input against strToVerify.
260 // \param strToVerify Value to compare against user input.
261 // \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
262 // \param dlgLine0 String shown on dialog line 0. Converts to localized string if contains a positive integer.
263 // \param dlgLine1 String shown on dialog line 1. Converts to localized string if contains a positive integer.
264 // \param dlgLine2 String shown on dialog line 2. Converts to localized string if contains a positive integer.
265 // \param bGetUserInput If set as true and return=true, strToVerify is overwritten with user input string.
266 // \param bHideInputChars Masks user input as asterisks if set as true. Currently not yet implemented.
267 // \return true if successful display and user input. false if unsuccessful display, no user input, or canceled editing.
268 bool CGUIDialogGamepad::ShowAndVerifyInput(std::string
& strToVerify
, const std::string
& dlgHeading
,
269 const std::string
& dlgLine0
, const std::string
& dlgLine1
,
270 const std::string
& dlgLine2
, bool bGetUserInput
, bool bHideInputChars
)
272 // Prompt user for password input
273 CGUIDialogGamepad
*pDialog
= CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogGamepad
>(WINDOW_DIALOG_GAMEPAD
);
274 pDialog
->m_strPassword
= strToVerify
;
275 pDialog
->m_bUserInputCleanup
= !bGetUserInput
;
276 pDialog
->m_bHideInputChars
= bHideInputChars
;
278 // HACK: This won't work if the label specified is actually a positive numeric value, but that's very unlikely
279 if (!StringUtils::IsNaturalNumber(dlgHeading
))
280 pDialog
->SetHeading(CVariant
{dlgHeading
});
282 pDialog
->SetHeading(CVariant
{atoi(dlgHeading
.c_str())});
284 if (!StringUtils::IsNaturalNumber(dlgLine0
))
285 pDialog
->SetLine(0, CVariant
{dlgLine0
});
287 pDialog
->SetLine(0, CVariant
{atoi(dlgLine0
.c_str())});
289 if (!StringUtils::IsNaturalNumber(dlgLine1
))
290 pDialog
->SetLine(1, CVariant
{dlgLine1
});
292 pDialog
->SetLine(1, CVariant
{atoi(dlgLine1
.c_str())});
294 if (!StringUtils::IsNaturalNumber(dlgLine2
))
295 pDialog
->SetLine(2, CVariant
{dlgLine2
});
297 pDialog
->SetLine(2, CVariant
{atoi(dlgLine2
.c_str())});
299 CGUIComponent
* gui
= CServiceBroker::GetGUI();
301 gui
->GetAudioManager().Enable(false); // don't do sounds during pwd input
306 gui
->GetAudioManager().Enable(true);
308 if (bGetUserInput
&& !pDialog
->IsCanceled())
310 strToVerify
= CDigest::Calculate(CDigest::Type::MD5
, pDialog
->m_strUserInput
);
311 pDialog
->m_strUserInput
= "";
314 if (!pDialog
->IsConfirmed() || pDialog
->IsCanceled())
316 // user canceled out or entered an incorrect password
320 // user entered correct password
324 bool CGUIDialogGamepad::IsCanceled() const