diff options
Diffstat (limited to 'xbmc/dialogs/GUIDialogNumeric.cpp')
-rw-r--r-- | xbmc/dialogs/GUIDialogNumeric.cpp | 916 |
1 files changed, 916 insertions, 0 deletions
diff --git a/xbmc/dialogs/GUIDialogNumeric.cpp b/xbmc/dialogs/GUIDialogNumeric.cpp new file mode 100644 index 0000000..182cf6a --- /dev/null +++ b/xbmc/dialogs/GUIDialogNumeric.cpp @@ -0,0 +1,916 @@ +/* + * 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 "GUIDialogNumeric.h" + +#include "ServiceBroker.h" +#include "XBDateTime.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUILabelControl.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "input/Key.h" +#include "input/XBMC_vkeys.h" +#include "interfaces/AnnouncementManager.h" +#include "messaging/helpers/DialogOKHelper.h" +#include "utils/Digest.h" +#include "utils/StringUtils.h" +#include "utils/Variant.h" + +#include <cassert> + +#define CONTROL_HEADING_LABEL 1 +#define CONTROL_INPUT_LABEL 4 +#define CONTROL_NUM0 10 +#define CONTROL_NUM9 19 +#define CONTROL_PREVIOUS 20 +#define CONTROL_ENTER 21 +#define CONTROL_NEXT 22 +#define CONTROL_BACKSPACE 23 + +using namespace KODI::MESSAGING; +using KODI::UTILITY::CDigest; + +CGUIDialogNumeric::CGUIDialogNumeric(void) + : CGUIDialog(WINDOW_DIALOG_NUMERIC, "DialogNumeric.xml"), + m_bConfirmed{false}, + m_bCanceled{false}, + m_mode{INPUT_PASSWORD}, + m_block{}, + m_lastblock{}, + m_dirty{false} +{ + memset(&m_datetime, 0, sizeof(KODI::TIME::SystemTime)); + m_loadType = KEEP_IN_MEMORY; +} + +CGUIDialogNumeric::~CGUIDialogNumeric(void) = default; + +void CGUIDialogNumeric::OnInitWindow() +{ + CGUIDialog::OnInitWindow(); + + CVariant data; + switch (m_mode) + { + case INPUT_TIME: + data["type"] = "time"; + break; + case INPUT_DATE: + data["type"] = "date"; + break; + case INPUT_IP_ADDRESS: + data["type"] = "ip"; + break; + case INPUT_PASSWORD: + data["type"] = "numericpassword"; + break; + case INPUT_NUMBER: + data["type"] = "number"; + break; + case INPUT_TIME_SECONDS: + data["type"] = "seconds"; + break; + default: + data["type"] = "keyboard"; + break; + } + + const CGUIControl *control = GetControl(CONTROL_HEADING_LABEL); + if (control != nullptr) + data["title"] = control->GetDescription(); + + data["value"] = GetOutputString(); + + CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Input, "OnInputRequested", data); +} + +void CGUIDialogNumeric::OnDeinitWindow(int nextWindowID) +{ + // call base class + CGUIDialog::OnDeinitWindow(nextWindowID); + + CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Input, "OnInputFinished"); +} + +bool CGUIDialogNumeric::OnAction(const CAction &action) +{ + if (action.GetID() == ACTION_NEXT_ITEM) + OnNext(); + else if (action.GetID() == ACTION_PREV_ITEM) + OnPrevious(); + else if (action.GetID() == ACTION_BACKSPACE) + OnBackSpace(); + else if (action.GetID() == ACTION_ENTER) + OnOK(); + else if (action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) + OnNumber(action.GetID() - REMOTE_0); + else if (action.GetID() >= KEY_VKEY && action.GetID() < KEY_UNICODE) + { + // input from the keyboard (vkey, not ascii) + uint8_t b = action.GetID() & 0xFF; + if (b == XBMCVK_LEFT) + OnPrevious(); + else if (b == XBMCVK_RIGHT) + OnNext(); + else if (b == XBMCVK_RETURN || b == XBMCVK_NUMPADENTER) + OnOK(); + else if (b == XBMCVK_BACK) + OnBackSpace(); + else if (b == XBMCVK_ESCAPE) + OnCancel(); + } + else if (action.GetID() == KEY_UNICODE) + { // input from the keyboard + if (action.GetUnicode() == 10 || action.GetUnicode() == 13) + OnOK(); // enter + else if (action.GetUnicode() == 8) + OnBackSpace(); // backspace + else if (action.GetUnicode() == 27) + OnCancel(); // escape + else if (action.GetUnicode() == 46) + OnNext(); // '.' + else if (action.GetUnicode() >= 48 && action.GetUnicode() < 58) // number + OnNumber(action.GetUnicode() - 48); + } + else + return CGUIDialog::OnAction(action); + + return true; +} + +bool CGUIDialogNumeric::OnBack(int actionID) +{ + OnCancel(); + return true; +} + +bool CGUIDialogNumeric::OnMessage(CGUIMessage& message) +{ + switch ( message.GetMessage() ) + { + case GUI_MSG_WINDOW_INIT: + { + m_bConfirmed = false; + m_bCanceled = false; + m_dirty = false; + return CGUIDialog::OnMessage(message); + } + break; + + case GUI_MSG_CLICKED: + { + int iControl = message.GetSenderId(); + m_bConfirmed = false; + m_bCanceled = false; + if (CONTROL_NUM0 <= iControl && iControl <= CONTROL_NUM9) // User numeric entry via dialog button UI + { + OnNumber(iControl - 10); + return true; + } + else if (iControl == CONTROL_PREVIOUS) + { + OnPrevious(); + return true; + } + else if (iControl == CONTROL_NEXT) + { + OnNext(); + return true; + } + else if (iControl == CONTROL_BACKSPACE) + { + OnBackSpace(); + return true; + } + else if (iControl == CONTROL_ENTER) + { + OnOK(); + return true; + } + } + break; + + case GUI_MSG_SET_TEXT: + SetMode(m_mode, message.GetLabel()); + + // close the dialog if requested + if (message.GetParam1() > 0) + OnOK(); + break; + } + return CGUIDialog::OnMessage(message); +} + +void CGUIDialogNumeric::OnBackSpace() +{ + if (!m_dirty && m_block) + { + --m_block; + return; + } + if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD) + { // just go back one character + if (!m_number.empty()) + m_number.erase(m_number.length() - 1); + } + else if (m_mode == INPUT_IP_ADDRESS) + { + if (m_ip[m_block]) + m_ip[m_block] /= 10; + else if (m_block) + { + --m_block; + m_dirty = false; + } + } + else if (m_mode == INPUT_TIME) + { + if (m_block == 0) + m_datetime.hour /= 10; + else if (m_datetime.minute) + m_datetime.minute /= 10; + else + { + m_block = 0; + m_dirty = false; + } + } + else if (m_mode == INPUT_TIME_SECONDS) + { + if (m_block == 0) + m_datetime.hour /= 10; + else if (m_block == 1) + { + if (m_datetime.minute) + m_datetime.minute /= 10; + else + { + m_block = 0; + m_dirty = false; + } + } + else if (m_datetime.second) + m_datetime.minute /= 10; + else + { + m_block = 0; + m_dirty = false; + } + } + else if (m_mode == INPUT_DATE) + { + if (m_block == 0) + m_datetime.day /= 10; + else if (m_block == 1) + { + if (m_datetime.month) + m_datetime.month /= 10; + else + { + m_block = 0; + m_dirty = false; + } + } + else if (m_datetime.year) // m_block == 2 + m_datetime.year /= 10; + else + { + m_block = 1; + m_dirty = false; + } + } +} + +void CGUIDialogNumeric::OnPrevious() +{ + if (m_block) + m_block--; + m_dirty = false; +} + +void CGUIDialogNumeric::OnNext() +{ + if (m_mode == INPUT_IP_ADDRESS && m_block==0 && m_ip[0]==0) + return; + + if (m_block < m_lastblock) + m_block++; + m_dirty = false; + if (m_mode == INPUT_DATE) + VerifyDate(m_block == 2); +} + +void CGUIDialogNumeric::FrameMove() +{ + std::string strLabel; + unsigned int start = 0; + unsigned int end = 0; + if (m_mode == INPUT_PASSWORD) + strLabel.assign(m_number.length(), '*'); + else if (m_mode == INPUT_NUMBER) + strLabel = m_number; + else if (m_mode == INPUT_TIME) + { // format up the time + strLabel = StringUtils::Format("{:2}:{:02}", m_datetime.hour, m_datetime.minute); + start = m_block * 3; + end = m_block * 3 + 2; + } + else if (m_mode == INPUT_TIME_SECONDS) + { // format up the time + strLabel = StringUtils::Format("{:2}:{:02}:{:02}", m_datetime.hour, m_datetime.minute, + m_datetime.second); + start = m_block * 3; + end = m_block * 3 + 2; + } + else if (m_mode == INPUT_DATE) + { // format up the date + strLabel = + StringUtils::Format("{:2}/{:2}/{:4}", m_datetime.day, m_datetime.month, m_datetime.year); + start = m_block * 3; + end = m_block * 3 + 2; + if (m_block == 2) + end = m_block * 3 + 4; + } + else if (m_mode == INPUT_IP_ADDRESS) + { // format up the date + strLabel = StringUtils::Format("{:3}.{:3}.{:3}.{:3}", m_ip[0], m_ip[1], m_ip[2], m_ip[3]); + start = m_block * 4; + end = m_block * 4 + 3; + } + CGUILabelControl *pLabel = dynamic_cast<CGUILabelControl *>(GetControl(CONTROL_INPUT_LABEL)); + if (pLabel) + { + pLabel->SetLabel(strLabel); + pLabel->SetHighlight(start, end); + } + CGUIDialog::FrameMove(); +} + +void CGUIDialogNumeric::OnNumber(uint32_t num) +{ + ResetAutoClose(); + + switch (m_mode) + { + case INPUT_NUMBER: + case INPUT_PASSWORD: + m_number += num + '0'; + break; + case INPUT_TIME: + HandleInputTime(num); + break; + case INPUT_TIME_SECONDS: + HandleInputSeconds(num); + break; + case INPUT_DATE: + HandleInputDate(num); + break; + case INPUT_IP_ADDRESS: + HandleInputIP(num); + break; + } +} + +void CGUIDialogNumeric::SetMode(INPUT_MODE mode, const KODI::TIME::SystemTime& initial) +{ + m_mode = mode; + m_block = 0; + m_lastblock = 0; + if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS || m_mode == INPUT_DATE) + { + m_datetime = initial; + m_lastblock = (m_mode != INPUT_TIME) ? 2 : 1; + } +} + +void CGUIDialogNumeric::SetMode(INPUT_MODE mode, const std::string &initial) +{ + m_mode = mode; + m_block = 0; + m_lastblock = 0; + if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS || m_mode == INPUT_DATE) + { + CDateTime dateTime; + if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS) + { + // check if we have a pure number + if (initial.find_first_not_of("0123456789") == std::string::npos) + { + long seconds = strtol(initial.c_str(), nullptr, 10); + dateTime = seconds; + } + else + { + std::string tmp = initial; + // if we are handling seconds and if the string only contains + // "mm:ss" we need to add dummy "hh:" to get "hh:mm:ss" + if (m_mode == INPUT_TIME_SECONDS && tmp.length() <= 5) + tmp = "00:" + tmp; + dateTime.SetFromDBTime(tmp); + } + } + else if (m_mode == INPUT_DATE) + { + std::string tmp = initial; + StringUtils::Replace(tmp, '/', '.'); + dateTime.SetFromDBDate(tmp); + } + + if (!dateTime.IsValid()) + return; + + dateTime.GetAsSystemTime(m_datetime); + m_lastblock = (m_mode == INPUT_DATE) ? 2 : 1; + } + else if (m_mode == INPUT_IP_ADDRESS) + { + m_lastblock = 3; + auto blocks = StringUtils::Split(initial, '.'); + if (blocks.size() != 4) + return; + + for (size_t i = 0; i < blocks.size(); ++i) + { + if (blocks[i].length() > 3) + return; + + m_ip[i] = static_cast<uint8_t>(atoi(blocks[i].c_str())); + } + } + else if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD) + m_number = initial; +} + +KODI::TIME::SystemTime CGUIDialogNumeric::GetOutput() const +{ + assert(m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS || m_mode == INPUT_DATE); + return m_datetime; +} + +std::string CGUIDialogNumeric::GetOutputString() const +{ + switch (m_mode) + { + case INPUT_DATE: + return StringUtils::Format("{:02}/{:02}/{:04}", m_datetime.day, m_datetime.month, + m_datetime.year); + case INPUT_TIME: + return StringUtils::Format("{}:{:02}", m_datetime.hour, m_datetime.minute); + case INPUT_TIME_SECONDS: + return StringUtils::Format("{}:{:02}:{:02}", m_datetime.hour, m_datetime.minute, + m_datetime.second); + case INPUT_IP_ADDRESS: + return StringUtils::Format("{}.{}.{}.{}", m_ip[0], m_ip[1], m_ip[2], m_ip[3]); + case INPUT_NUMBER: + case INPUT_PASSWORD: + return m_number; + } + + //should never get here + return std::string(); +} + +bool CGUIDialogNumeric::ShowAndGetSeconds(std::string &timeString, const std::string &heading) +{ + CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC); + if (!pDialog) return false; + int seconds = StringUtils::TimeStringToSeconds(timeString); + KODI::TIME::SystemTime time = {}; + time.hour = seconds / 3600; + time.minute = (seconds - time.hour * 3600) / 60; + time.second = seconds - time.hour * 3600 - time.minute * 60; + pDialog->SetMode(INPUT_TIME_SECONDS, time); + pDialog->SetHeading(heading); + pDialog->Open(); + if (!pDialog->IsConfirmed() || pDialog->IsCanceled()) + return false; + time = pDialog->GetOutput(); + seconds = time.hour * 3600 + time.minute * 60 + time.second; + timeString = StringUtils::SecondsToTimeString(seconds); + return true; +} + +bool CGUIDialogNumeric::ShowAndGetTime(KODI::TIME::SystemTime& time, const std::string& heading) +{ + CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC); + if (!pDialog) return false; + pDialog->SetMode(INPUT_TIME, time); + pDialog->SetHeading(heading); + pDialog->Open(); + if (!pDialog->IsConfirmed() || pDialog->IsCanceled()) + return false; + time = pDialog->GetOutput(); + return true; +} + +bool CGUIDialogNumeric::ShowAndGetDate(KODI::TIME::SystemTime& date, const std::string& heading) +{ + CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC); + if (!pDialog) return false; + pDialog->SetMode(INPUT_DATE, date); + pDialog->SetHeading(heading); + pDialog->Open(); + if (!pDialog->IsConfirmed() || pDialog->IsCanceled()) + return false; + date = pDialog->GetOutput(); + return true; +} + +bool CGUIDialogNumeric::ShowAndGetIPAddress(std::string &IPAddress, const std::string &heading) +{ + CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC); + if (!pDialog) return false; + pDialog->SetMode(INPUT_IP_ADDRESS, IPAddress); + pDialog->SetHeading(heading); + pDialog->Open(); + if (!pDialog->IsConfirmed() || pDialog->IsCanceled()) + return false; + IPAddress = pDialog->GetOutputString(); + return true; +} + +bool CGUIDialogNumeric::ShowAndGetNumber(std::string& strInput, const std::string &strHeading, unsigned int iAutoCloseTimeoutMs /* = 0 */, bool bSetHidden /* = false */) +{ + // Prompt user for password input + CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC); + pDialog->SetHeading( strHeading ); + + if (bSetHidden) + pDialog->SetMode(INPUT_PASSWORD, strInput); + else + pDialog->SetMode(INPUT_NUMBER, strInput); + if (iAutoCloseTimeoutMs) + pDialog->SetAutoClose(iAutoCloseTimeoutMs); + + pDialog->Open(); + + if (!pDialog->IsAutoClosed() && (!pDialog->IsConfirmed() || pDialog->IsCanceled())) + return false; + strInput = pDialog->GetOutputString(); + return true; +} + +// \brief Show numeric 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 CGUIDialogNumeric::ShowAndVerifyNewPassword(std::string& strNewPassword) +{ + // Prompt user for password input + std::string strUserInput; + InputVerificationResult ret = ShowAndVerifyInput(strUserInput, g_localizeStrings.Get(12340), false); + if (ret != InputVerificationResult::SUCCESS) + { + if (ret == InputVerificationResult::FAILED) + { + // 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 + ret = ShowAndVerifyInput(strUserInput, g_localizeStrings.Get(12341), true); + if (ret != InputVerificationResult::SUCCESS) + { + if (ret == InputVerificationResult::FAILED) + { + // 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 numeric keypad and verify user input against strPassword. +// \param strPassword Value to compare against user input. +// \param strHeading 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 CGUIDialogNumeric::ShowAndVerifyPassword(std::string& strPassword, const std::string& strHeading, int iRetries) +{ + std::string strTempHeading = strHeading; + if (iRetries > 0) + { + // Show a string telling user they have iRetries retries left + strTempHeading = StringUtils::Format("{}. {} {} {}", strHeading, g_localizeStrings.Get(12342), + iRetries, g_localizeStrings.Get(12343)); + } + + // make a copy of strPassword to prevent from overwriting it later + std::string strPassTemp = strPassword; + InputVerificationResult ret = ShowAndVerifyInput(strPassTemp, strTempHeading, true); + if (ret == InputVerificationResult::SUCCESS) + return 0; // user entered correct password + + if (ret == InputVerificationResult::CANCELED) + return -1; // user canceled out + + return 1; // user must have entered an incorrect password +} + +// \brief Show numeric keypad and verify user input against strToVerify. +// \param strToVerify Value to compare against user input. +// \param dlgHeading String shown on dialog title. +// \param bVerifyInput If set as true we verify the users input versus strToVerify. +// \return the result of the check (success, failed, or canceled by user). +InputVerificationResult CGUIDialogNumeric::ShowAndVerifyInput(std::string& strToVerify, const std::string& dlgHeading, bool bVerifyInput) +{ + // Prompt user for password input + CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC); + pDialog->SetHeading(dlgHeading); + + std::string strInput; + if (!bVerifyInput) + strInput = strToVerify; + + pDialog->SetMode(INPUT_PASSWORD, strInput); + pDialog->Open(); + + strInput = pDialog->GetOutputString(); + + if (!pDialog->IsConfirmed() || pDialog->IsCanceled()) + { + // user canceled out + strToVerify = ""; + return InputVerificationResult::CANCELED; + } + + const std::string md5pword2 = CDigest::Calculate(CDigest::Type::MD5, strInput); + + if (!bVerifyInput) + { + strToVerify = md5pword2; + return InputVerificationResult::SUCCESS; + } + + return StringUtils::EqualsNoCase(strToVerify, md5pword2) ? InputVerificationResult::SUCCESS : InputVerificationResult::FAILED; +} + +bool CGUIDialogNumeric::IsConfirmed() const +{ + return m_bConfirmed; +} + +bool CGUIDialogNumeric::IsCanceled() const +{ + return m_bCanceled; +} + +void CGUIDialogNumeric::SetHeading(const std::string& strHeading) +{ + Initialize(); + CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), CONTROL_HEADING_LABEL); + msg.SetLabel(strHeading); + OnMessage(msg); +} + +void CGUIDialogNumeric::VerifyDate(bool checkYear) +{ + if (m_datetime.day == 0) + m_datetime.day = 1; + if (m_datetime.month == 0) + m_datetime.month = 1; + // check for number of days in the month + if (m_datetime.day == 31) + { + if (m_datetime.month == 4 || m_datetime.month == 6 || m_datetime.month == 9 || + m_datetime.month == 11) + m_datetime.day = 30; + } + if (m_datetime.month == 2 && m_datetime.day > 28) + { + m_datetime.day = 29; // max in february. + if (checkYear) + { + // leap years occur when the year is divisible by 4 but not by 100, or the year is divisible by 400 + // thus they don't occur, if the year has a remainder when divided by 4, or when the year is divisible by 100 but not by 400 + if ((m_datetime.year % 4) || (!(m_datetime.year % 100) && (m_datetime.year % 400))) + m_datetime.day = 28; + } + } +} + +void CGUIDialogNumeric::OnOK() +{ + m_bConfirmed = true; + m_bCanceled = false; + Close(); +} + +void CGUIDialogNumeric::OnCancel() +{ + m_bConfirmed = false; + m_bCanceled = true; + Close(); +} + +void CGUIDialogNumeric::HandleInputIP(uint32_t num) +{ + if (m_dirty && ((m_ip[m_block] < 25) || (m_ip[m_block] == 25 && num < 6) || !(m_block == 0 && num == 0))) + { + m_ip[m_block] *= 10; + m_ip[m_block] += num; + } + else + m_ip[m_block] = num; + + if (m_ip[m_block] > 25 || (m_ip[m_block] == 0 && num == 0)) + { + ++m_block; + if (m_block > 3) + m_block = 0; + m_dirty = false; + } + else + m_dirty = true; +} + +void CGUIDialogNumeric::HandleInputDate(uint32_t num) +{ + if (m_block == 0) // day of month + { + if (m_dirty && (m_datetime.day < 3 || num < 2)) + { + m_datetime.day *= 10; + m_datetime.day += num; + } + else + m_datetime.day = num; + + if (m_datetime.day > 3) + { + m_block = 1; // move to months + m_dirty = false; + } + else + m_dirty = true; + } + else if (m_block == 1) // months + { + if (m_dirty && num < 3) + { + m_datetime.month *= 10; + m_datetime.month += num; + } + else + m_datetime.month = num; + + if (m_datetime.month > 1) + { + VerifyDate(false); + m_block = 2; // move to year + m_dirty = false; + } + else + m_dirty = true; + } + else // year + { + if (m_dirty && m_datetime.year < 1000) // have taken input + { + m_datetime.year *= 10; + m_datetime.year += num; + } + else + m_datetime.year = num; + + if (m_datetime.year > 1000) + { + VerifyDate(true); + m_block = 0; // move to day of month + m_dirty = false; + } + else + m_dirty = true; + } +} + +void CGUIDialogNumeric::HandleInputSeconds(uint32_t num) +{ + if (m_block == 0) // hour + { + if (m_dirty) // have input the first digit + { + m_datetime.hour *= 10; + m_datetime.hour += num; + m_block = 1; // move to minutes - allows up to 99 hours + m_dirty = false; + } + else // this is the first digit + { + m_datetime.hour = num; + m_dirty = true; + } + } + else if (m_block == 1) // minute + { + if (m_dirty) // have input the first digit + { + m_datetime.minute *= 10; + m_datetime.minute += num; + m_block = 2; // move to seconds - allows up to 99 minutes + m_dirty = false; + } + else // this is the first digit + { + m_datetime.minute = num; + if (num > 5) + { + m_block = 2; // move to seconds + m_dirty = false; + } + else + m_dirty = true; + } + } + else // seconds + { + if (m_dirty) // have input the first digit + { + m_datetime.second *= 10; + m_datetime.second += num; + m_block = 0; // move to hours + m_dirty = false; + } + else // this is the first digit + { + m_datetime.second = num; + if (num > 5) + { + m_block = 0; // move to hours + m_dirty = false; + } + else + m_dirty = true; + } + } +} + +void CGUIDialogNumeric::HandleInputTime(uint32_t num) +{ + if (m_block == 0) // hour + { + if (m_dirty) // have input the first digit + { + if (m_datetime.hour < 2 || num < 4) + { + m_datetime.hour *= 10; + m_datetime.hour += num; + } + else + m_datetime.hour = num; + + m_block = 1; // move to minutes + m_dirty = false; + } + else // this is the first digit + { + m_datetime.hour = num; + + if (num > 2) + { + m_block = 1; // move to minutes + m_dirty = false; + } + else + m_dirty = true; + } + } + else // minute + { + if (m_dirty) // have input the first digit + { + m_datetime.minute *= 10; + m_datetime.minute += num; + m_block = 0; // move to hours + m_dirty = false; + } + else // this is the first digit + { + m_datetime.minute = num; + + if (num > 5) + { + m_block = 0; // move to hours + m_dirty = false; + } + else + m_dirty = true; + } + } +} + |