[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / dialogs / GUIDialogNumeric.cpp
blob04d8c1d72c325c9bf74e411d7fb406b2e809f75b
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 "GUIDialogNumeric.h"
11 #include "ServiceBroker.h"
12 #include "XBDateTime.h"
13 #include "guilib/GUIComponent.h"
14 #include "guilib/GUILabelControl.h"
15 #include "guilib/GUIWindowManager.h"
16 #include "guilib/LocalizeStrings.h"
17 #include "input/actions/Action.h"
18 #include "input/actions/ActionIDs.h"
19 #include "input/keyboard/KeyIDs.h"
20 #include "input/keyboard/XBMC_vkeys.h"
21 #include "interfaces/AnnouncementManager.h"
22 #include "messaging/helpers/DialogOKHelper.h"
23 #include "utils/Digest.h"
24 #include "utils/StringUtils.h"
25 #include "utils/Variant.h"
27 #include <cassert>
29 #define CONTROL_HEADING_LABEL 1
30 #define CONTROL_INPUT_LABEL 4
31 #define CONTROL_NUM0 10
32 #define CONTROL_NUM9 19
33 #define CONTROL_PREVIOUS 20
34 #define CONTROL_ENTER 21
35 #define CONTROL_NEXT 22
36 #define CONTROL_BACKSPACE 23
38 using namespace KODI::MESSAGING;
39 using KODI::UTILITY::CDigest;
41 CGUIDialogNumeric::CGUIDialogNumeric(void) : CGUIDialog(WINDOW_DIALOG_NUMERIC, "DialogNumeric.xml")
43 memset(&m_datetime, 0, sizeof(KODI::TIME::SystemTime));
44 m_loadType = KEEP_IN_MEMORY;
47 CGUIDialogNumeric::~CGUIDialogNumeric(void) = default;
49 void CGUIDialogNumeric::OnInitWindow()
51 CGUIDialog::OnInitWindow();
53 CVariant data;
54 switch (m_mode)
56 case INPUT_TIME:
57 data["type"] = "time";
58 break;
59 case INPUT_DATE:
60 data["type"] = "date";
61 break;
62 case INPUT_IP_ADDRESS:
63 data["type"] = "ip";
64 break;
65 case INPUT_PASSWORD:
66 data["type"] = "numericpassword";
67 break;
68 case INPUT_NUMBER:
69 data["type"] = "number";
70 break;
71 case INPUT_TIME_SECONDS:
72 data["type"] = "seconds";
73 break;
74 default:
75 data["type"] = "keyboard";
76 break;
79 const CGUIControl *control = GetControl(CONTROL_HEADING_LABEL);
80 if (control != nullptr)
81 data["title"] = control->GetDescription();
83 data["value"] = GetOutputString();
85 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Input, "OnInputRequested", data);
88 void CGUIDialogNumeric::OnDeinitWindow(int nextWindowID)
90 // call base class
91 CGUIDialog::OnDeinitWindow(nextWindowID);
93 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Input, "OnInputFinished");
96 bool CGUIDialogNumeric::OnAction(const CAction &action)
98 if (action.GetID() == ACTION_NEXT_ITEM)
99 OnNext();
100 else if (action.GetID() == ACTION_PREV_ITEM)
101 OnPrevious();
102 else if (action.GetID() == ACTION_BACKSPACE)
103 OnBackSpace();
104 else if (action.GetID() == ACTION_ENTER)
105 OnOK();
106 else if (action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9)
107 OnNumber(action.GetID() - REMOTE_0);
108 else if (action.GetID() >= KEY_VKEY && action.GetID() < KEY_UNICODE)
110 // input from the keyboard (vkey, not ascii)
111 uint8_t b = action.GetID() & 0xFF;
112 if (b == XBMCVK_LEFT)
113 OnPrevious();
114 else if (b == XBMCVK_RIGHT)
115 OnNext();
116 else if (b == XBMCVK_RETURN || b == XBMCVK_NUMPADENTER)
117 OnOK();
118 else if (b == XBMCVK_BACK)
119 OnBackSpace();
120 else if (b == XBMCVK_ESCAPE)
121 OnCancel();
123 else if (action.GetID() == KEY_UNICODE)
124 { // input from the keyboard
125 if (action.GetUnicode() == 10 || action.GetUnicode() == 13)
126 OnOK(); // enter
127 else if (action.GetUnicode() == 8)
128 OnBackSpace(); // backspace
129 else if (action.GetUnicode() == 27)
130 OnCancel(); // escape
131 else if (action.GetUnicode() == 46)
132 OnNext(); // '.'
133 else if (action.GetUnicode() >= 48 && action.GetUnicode() < 58) // number
134 OnNumber(action.GetUnicode() - 48);
136 else
137 return CGUIDialog::OnAction(action);
139 return true;
142 bool CGUIDialogNumeric::OnBack(int actionID)
144 OnCancel();
145 return true;
148 bool CGUIDialogNumeric::OnMessage(CGUIMessage& message)
150 switch ( message.GetMessage() )
152 case GUI_MSG_WINDOW_INIT:
154 m_bConfirmed = false;
155 m_bCanceled = false;
156 m_dirty = false;
157 return CGUIDialog::OnMessage(message);
159 break;
161 case GUI_MSG_CLICKED:
163 int iControl = message.GetSenderId();
164 m_bConfirmed = false;
165 m_bCanceled = false;
166 if (CONTROL_NUM0 <= iControl && iControl <= CONTROL_NUM9) // User numeric entry via dialog button UI
168 OnNumber(iControl - 10);
169 return true;
171 else if (iControl == CONTROL_PREVIOUS)
173 OnPrevious();
174 return true;
176 else if (iControl == CONTROL_NEXT)
178 OnNext();
179 return true;
181 else if (iControl == CONTROL_BACKSPACE)
183 OnBackSpace();
184 return true;
186 else if (iControl == CONTROL_ENTER)
188 OnOK();
189 return true;
192 break;
194 case GUI_MSG_SET_TEXT:
195 SetMode(m_mode, message.GetLabel());
197 // close the dialog if requested
198 if (message.GetParam1() > 0)
199 OnOK();
200 break;
202 return CGUIDialog::OnMessage(message);
205 void CGUIDialogNumeric::OnBackSpace()
207 if (!m_dirty && m_block)
209 --m_block;
210 return;
212 if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD)
213 { // just go back one character
214 if (!m_number.empty())
215 m_number.erase(m_number.length() - 1);
217 else if (m_mode == INPUT_IP_ADDRESS)
219 if (m_ip[m_block])
220 m_ip[m_block] /= 10;
221 else if (m_block)
223 --m_block;
224 m_dirty = false;
227 else if (m_mode == INPUT_TIME)
229 if (m_block == 0)
230 m_datetime.hour /= 10;
231 else if (m_datetime.minute)
232 m_datetime.minute /= 10;
233 else
235 m_block = 0;
236 m_dirty = false;
239 else if (m_mode == INPUT_TIME_SECONDS)
241 if (m_block == 0)
242 m_datetime.hour /= 10;
243 else if (m_block == 1)
245 if (m_datetime.minute)
246 m_datetime.minute /= 10;
247 else
249 m_block = 0;
250 m_dirty = false;
253 else if (m_datetime.second)
254 m_datetime.minute /= 10;
255 else
257 m_block = 0;
258 m_dirty = false;
261 else if (m_mode == INPUT_DATE)
263 if (m_block == 0)
264 m_datetime.day /= 10;
265 else if (m_block == 1)
267 if (m_datetime.month)
268 m_datetime.month /= 10;
269 else
271 m_block = 0;
272 m_dirty = false;
275 else if (m_datetime.year) // m_block == 2
276 m_datetime.year /= 10;
277 else
279 m_block = 1;
280 m_dirty = false;
285 void CGUIDialogNumeric::OnPrevious()
287 if (m_block)
288 m_block--;
289 m_dirty = false;
292 void CGUIDialogNumeric::OnNext()
294 if (m_mode == INPUT_IP_ADDRESS && m_block==0 && m_ip[0]==0)
295 return;
297 if (m_block < m_lastblock)
298 m_block++;
299 m_dirty = false;
300 if (m_mode == INPUT_DATE)
301 VerifyDate(m_block == 2);
304 void CGUIDialogNumeric::FrameMove()
306 std::string strLabel;
307 unsigned int start = 0;
308 unsigned int end = 0;
309 if (m_mode == INPUT_PASSWORD)
310 strLabel.assign(m_number.length(), '*');
311 else if (m_mode == INPUT_NUMBER)
312 strLabel = m_number;
313 else if (m_mode == INPUT_TIME)
314 { // format up the time
315 strLabel = StringUtils::Format("{:2}:{:02}", m_datetime.hour, m_datetime.minute);
316 start = m_block * 3;
317 end = m_block * 3 + 2;
319 else if (m_mode == INPUT_TIME_SECONDS)
320 { // format up the time
321 strLabel = StringUtils::Format("{:2}:{:02}:{:02}", m_datetime.hour, m_datetime.minute,
322 m_datetime.second);
323 start = m_block * 3;
324 end = m_block * 3 + 2;
326 else if (m_mode == INPUT_DATE)
327 { // format up the date
328 strLabel =
329 StringUtils::Format("{:2}/{:2}/{:4}", m_datetime.day, m_datetime.month, m_datetime.year);
330 start = m_block * 3;
331 end = m_block * 3 + 2;
332 if (m_block == 2)
333 end = m_block * 3 + 4;
335 else if (m_mode == INPUT_IP_ADDRESS)
336 { // format up the date
337 strLabel = StringUtils::Format("{:3}.{:3}.{:3}.{:3}", m_ip[0], m_ip[1], m_ip[2], m_ip[3]);
338 start = m_block * 4;
339 end = m_block * 4 + 3;
341 CGUILabelControl *pLabel = dynamic_cast<CGUILabelControl *>(GetControl(CONTROL_INPUT_LABEL));
342 if (pLabel)
344 pLabel->SetLabel(strLabel);
345 pLabel->SetHighlight(start, end);
347 CGUIDialog::FrameMove();
350 void CGUIDialogNumeric::OnNumber(uint32_t num)
352 ResetAutoClose();
354 switch (m_mode)
356 case INPUT_NUMBER:
357 case INPUT_PASSWORD:
358 m_number += num + '0';
359 break;
360 case INPUT_TIME:
361 HandleInputTime(num);
362 break;
363 case INPUT_TIME_SECONDS:
364 HandleInputSeconds(num);
365 break;
366 case INPUT_DATE:
367 HandleInputDate(num);
368 break;
369 case INPUT_IP_ADDRESS:
370 HandleInputIP(num);
371 break;
375 void CGUIDialogNumeric::SetMode(INPUT_MODE mode, const KODI::TIME::SystemTime& initial)
377 m_mode = mode;
378 m_block = 0;
379 m_lastblock = 0;
380 if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS || m_mode == INPUT_DATE)
382 m_datetime = initial;
383 m_lastblock = (m_mode != INPUT_TIME) ? 2 : 1;
387 void CGUIDialogNumeric::SetMode(INPUT_MODE mode, const std::string &initial)
389 m_mode = mode;
390 m_block = 0;
391 m_lastblock = 0;
392 if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS || m_mode == INPUT_DATE)
394 CDateTime dateTime;
395 if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS)
397 // check if we have a pure number
398 if (initial.find_first_not_of("0123456789") == std::string::npos)
400 long seconds = strtol(initial.c_str(), nullptr, 10);
401 dateTime = seconds;
403 else
405 std::string tmp = initial;
406 // if we are handling seconds and if the string only contains
407 // "mm:ss" we need to add dummy "hh:" to get "hh:mm:ss"
408 if (m_mode == INPUT_TIME_SECONDS && tmp.length() <= 5)
409 tmp = "00:" + tmp;
410 dateTime.SetFromDBTime(tmp);
413 else if (m_mode == INPUT_DATE)
415 std::string tmp = initial;
416 StringUtils::Replace(tmp, '/', '.');
417 dateTime.SetFromDBDate(tmp);
420 if (!dateTime.IsValid())
421 return;
423 dateTime.GetAsSystemTime(m_datetime);
424 m_lastblock = (m_mode == INPUT_DATE) ? 2 : 1;
426 else if (m_mode == INPUT_IP_ADDRESS)
428 m_lastblock = 3;
429 auto blocks = StringUtils::Split(initial, '.');
430 if (blocks.size() != 4)
431 return;
433 for (size_t i = 0; i < blocks.size(); ++i)
435 if (blocks[i].length() > 3)
436 return;
438 m_ip[i] = static_cast<uint8_t>(atoi(blocks[i].c_str()));
441 else if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD)
442 m_number = initial;
445 KODI::TIME::SystemTime CGUIDialogNumeric::GetOutput() const
447 assert(m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS || m_mode == INPUT_DATE);
448 return m_datetime;
451 std::string CGUIDialogNumeric::GetOutputString() const
453 switch (m_mode)
455 case INPUT_DATE:
456 return StringUtils::Format("{:02}/{:02}/{:04}", m_datetime.day, m_datetime.month,
457 m_datetime.year);
458 case INPUT_TIME:
459 return StringUtils::Format("{}:{:02}", m_datetime.hour, m_datetime.minute);
460 case INPUT_TIME_SECONDS:
461 return StringUtils::Format("{}:{:02}:{:02}", m_datetime.hour, m_datetime.minute,
462 m_datetime.second);
463 case INPUT_IP_ADDRESS:
464 return StringUtils::Format("{}.{}.{}.{}", m_ip[0], m_ip[1], m_ip[2], m_ip[3]);
465 case INPUT_NUMBER:
466 case INPUT_PASSWORD:
467 return m_number;
470 //should never get here
471 return std::string();
474 bool CGUIDialogNumeric::ShowAndGetSeconds(std::string &timeString, const std::string &heading)
476 CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC);
477 if (!pDialog) return false;
478 int seconds = StringUtils::TimeStringToSeconds(timeString);
479 KODI::TIME::SystemTime time = {};
480 time.hour = seconds / 3600;
481 time.minute = (seconds - time.hour * 3600) / 60;
482 time.second = seconds - time.hour * 3600 - time.minute * 60;
483 pDialog->SetMode(INPUT_TIME_SECONDS, time);
484 pDialog->SetHeading(heading);
485 pDialog->Open();
486 if (!pDialog->IsConfirmed() || pDialog->IsCanceled())
487 return false;
488 time = pDialog->GetOutput();
489 seconds = time.hour * 3600 + time.minute * 60 + time.second;
490 timeString = StringUtils::SecondsToTimeString(seconds);
491 return true;
494 bool CGUIDialogNumeric::ShowAndGetTime(KODI::TIME::SystemTime& time, const std::string& heading)
496 CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC);
497 if (!pDialog) return false;
498 pDialog->SetMode(INPUT_TIME, time);
499 pDialog->SetHeading(heading);
500 pDialog->Open();
501 if (!pDialog->IsConfirmed() || pDialog->IsCanceled())
502 return false;
503 time = pDialog->GetOutput();
504 return true;
507 bool CGUIDialogNumeric::ShowAndGetDate(KODI::TIME::SystemTime& date, const std::string& heading)
509 CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC);
510 if (!pDialog) return false;
511 pDialog->SetMode(INPUT_DATE, date);
512 pDialog->SetHeading(heading);
513 pDialog->Open();
514 if (!pDialog->IsConfirmed() || pDialog->IsCanceled())
515 return false;
516 date = pDialog->GetOutput();
517 return true;
520 bool CGUIDialogNumeric::ShowAndGetIPAddress(std::string &IPAddress, const std::string &heading)
522 CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC);
523 if (!pDialog) return false;
524 pDialog->SetMode(INPUT_IP_ADDRESS, IPAddress);
525 pDialog->SetHeading(heading);
526 pDialog->Open();
527 if (!pDialog->IsConfirmed() || pDialog->IsCanceled())
528 return false;
529 IPAddress = pDialog->GetOutputString();
530 return true;
533 bool CGUIDialogNumeric::ShowAndGetNumber(std::string& strInput, const std::string &strHeading, unsigned int iAutoCloseTimeoutMs /* = 0 */, bool bSetHidden /* = false */)
535 // Prompt user for password input
536 CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC);
537 pDialog->SetHeading( strHeading );
539 if (bSetHidden)
540 pDialog->SetMode(INPUT_PASSWORD, strInput);
541 else
542 pDialog->SetMode(INPUT_NUMBER, strInput);
543 if (iAutoCloseTimeoutMs)
544 pDialog->SetAutoClose(iAutoCloseTimeoutMs);
546 pDialog->Open();
548 if (!pDialog->IsAutoClosed() && (!pDialog->IsConfirmed() || pDialog->IsCanceled()))
549 return false;
550 strInput = pDialog->GetOutputString();
551 return true;
554 // \brief Show numeric keypad twice to get and confirm a user-entered password string.
555 // \param strNewPassword String to preload into the keyboard accumulator. Overwritten with user input if return=true.
556 // \return true if successful display and user input entry/re-entry. false if unsuccessful display, no user input, or canceled editing.
557 bool CGUIDialogNumeric::ShowAndVerifyNewPassword(std::string& strNewPassword)
559 // Prompt user for password input
560 std::string strUserInput;
561 InputVerificationResult ret = ShowAndVerifyInput(strUserInput, g_localizeStrings.Get(12340), false);
562 if (ret != InputVerificationResult::SUCCESS)
564 if (ret == InputVerificationResult::FAILED)
566 // Show error to user saying the password entry was blank
567 HELPERS::ShowOKDialogText(CVariant{12357}, CVariant{12358}); // Password is empty/blank
569 return false;
572 if (strUserInput.empty())
573 // user canceled out
574 return false;
576 // Prompt again for password input, this time sending previous input as the password to verify
577 ret = ShowAndVerifyInput(strUserInput, g_localizeStrings.Get(12341), true);
578 if (ret != InputVerificationResult::SUCCESS)
580 if (ret == InputVerificationResult::FAILED)
582 // Show error to user saying the password re-entry failed
583 HELPERS::ShowOKDialogText(CVariant{12357}, CVariant{12344}); // Password do not match
585 return false;
588 // password entry and re-entry succeeded
589 strNewPassword = strUserInput;
590 return true;
593 // \brief Show numeric keypad and verify user input against strPassword.
594 // \param strPassword Value to compare against user input.
595 // \param strHeading String shown on dialog title. Converts to localized string if contains a positive integer.
596 // \param iRetries If greater than 0, shows "Incorrect password, %d retries left" on dialog line 2, else line 2 is blank.
597 // \return 0 if successful display and user input. 1 if unsuccessful input. -1 if no user input or canceled editing.
598 int CGUIDialogNumeric::ShowAndVerifyPassword(std::string& strPassword, const std::string& strHeading, int iRetries)
600 std::string strTempHeading = strHeading;
601 if (iRetries > 0)
603 // Show a string telling user they have iRetries retries left
604 strTempHeading = StringUtils::Format("{}. {} {} {}", strHeading, g_localizeStrings.Get(12342),
605 iRetries, g_localizeStrings.Get(12343));
608 // make a copy of strPassword to prevent from overwriting it later
609 std::string strPassTemp = strPassword;
610 InputVerificationResult ret = ShowAndVerifyInput(strPassTemp, strTempHeading, true);
611 if (ret == InputVerificationResult::SUCCESS)
612 return 0; // user entered correct password
614 if (ret == InputVerificationResult::CANCELED)
615 return -1; // user canceled out
617 return 1; // user must have entered an incorrect password
620 // \brief Show numeric keypad and verify user input against strToVerify.
621 // \param strToVerify Value to compare against user input.
622 // \param dlgHeading String shown on dialog title.
623 // \param bVerifyInput If set as true we verify the users input versus strToVerify.
624 // \return the result of the check (success, failed, or canceled by user).
625 InputVerificationResult CGUIDialogNumeric::ShowAndVerifyInput(std::string& strToVerify, const std::string& dlgHeading, bool bVerifyInput)
627 // Prompt user for password input
628 CGUIDialogNumeric *pDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC);
629 pDialog->SetHeading(dlgHeading);
631 std::string strInput;
632 if (!bVerifyInput)
633 strInput = strToVerify;
635 pDialog->SetMode(INPUT_PASSWORD, strInput);
636 pDialog->Open();
638 strInput = pDialog->GetOutputString();
640 if (!pDialog->IsConfirmed() || pDialog->IsCanceled())
642 // user canceled out
643 strToVerify = "";
644 return InputVerificationResult::CANCELED;
647 const std::string md5pword2 = CDigest::Calculate(CDigest::Type::MD5, strInput);
649 if (!bVerifyInput)
651 strToVerify = md5pword2;
652 return InputVerificationResult::SUCCESS;
655 return StringUtils::EqualsNoCase(strToVerify, md5pword2) ? InputVerificationResult::SUCCESS : InputVerificationResult::FAILED;
658 bool CGUIDialogNumeric::IsConfirmed() const
660 return m_bConfirmed;
663 bool CGUIDialogNumeric::IsCanceled() const
665 return m_bCanceled;
668 void CGUIDialogNumeric::SetHeading(const std::string& strHeading)
670 Initialize();
671 CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), CONTROL_HEADING_LABEL);
672 msg.SetLabel(strHeading);
673 OnMessage(msg);
676 void CGUIDialogNumeric::VerifyDate(bool checkYear)
678 if (m_datetime.day == 0)
679 m_datetime.day = 1;
680 if (m_datetime.month == 0)
681 m_datetime.month = 1;
682 // check for number of days in the month
683 if (m_datetime.day == 31)
685 if (m_datetime.month == 4 || m_datetime.month == 6 || m_datetime.month == 9 ||
686 m_datetime.month == 11)
687 m_datetime.day = 30;
689 if (m_datetime.month == 2 && m_datetime.day > 28)
691 m_datetime.day = 29; // max in february.
692 if (checkYear)
694 // leap years occur when the year is divisible by 4 but not by 100, or the year is divisible by 400
695 // 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
696 if ((m_datetime.year % 4) || (!(m_datetime.year % 100) && (m_datetime.year % 400)))
697 m_datetime.day = 28;
702 void CGUIDialogNumeric::OnOK()
704 m_bConfirmed = true;
705 m_bCanceled = false;
706 Close();
709 void CGUIDialogNumeric::OnCancel()
711 m_bConfirmed = false;
712 m_bCanceled = true;
713 Close();
716 void CGUIDialogNumeric::HandleInputIP(uint32_t num)
718 if (m_dirty && ((m_ip[m_block] < 25) || (m_ip[m_block] == 25 && num < 6) || !(m_block == 0 && num == 0)))
720 m_ip[m_block] *= 10;
721 m_ip[m_block] += num;
723 else
724 m_ip[m_block] = num;
726 if (m_ip[m_block] > 25 || (m_ip[m_block] == 0 && num == 0))
728 ++m_block;
729 if (m_block > 3)
730 m_block = 0;
731 m_dirty = false;
733 else
734 m_dirty = true;
737 void CGUIDialogNumeric::HandleInputDate(uint32_t num)
739 if (m_block == 0) // day of month
741 if (m_dirty && (m_datetime.day < 3 || num < 2))
743 m_datetime.day *= 10;
744 m_datetime.day += num;
746 else
747 m_datetime.day = num;
749 if (m_datetime.day > 3)
751 m_block = 1; // move to months
752 m_dirty = false;
754 else
755 m_dirty = true;
757 else if (m_block == 1) // months
759 if (m_dirty && num < 3)
761 m_datetime.month *= 10;
762 m_datetime.month += num;
764 else
765 m_datetime.month = num;
767 if (m_datetime.month > 1)
769 VerifyDate(false);
770 m_block = 2; // move to year
771 m_dirty = false;
773 else
774 m_dirty = true;
776 else // year
778 if (m_dirty && m_datetime.year < 1000) // have taken input
780 m_datetime.year *= 10;
781 m_datetime.year += num;
783 else
784 m_datetime.year = num;
786 if (m_datetime.year > 1000)
788 VerifyDate(true);
789 m_block = 0; // move to day of month
790 m_dirty = false;
792 else
793 m_dirty = true;
797 void CGUIDialogNumeric::HandleInputSeconds(uint32_t num)
799 if (m_block == 0) // hour
801 if (m_dirty) // have input the first digit
803 m_datetime.hour *= 10;
804 m_datetime.hour += num;
805 m_block = 1; // move to minutes - allows up to 99 hours
806 m_dirty = false;
808 else // this is the first digit
810 m_datetime.hour = num;
811 m_dirty = true;
814 else if (m_block == 1) // minute
816 if (m_dirty) // have input the first digit
818 m_datetime.minute *= 10;
819 m_datetime.minute += num;
820 m_block = 2; // move to seconds - allows up to 99 minutes
821 m_dirty = false;
823 else // this is the first digit
825 m_datetime.minute = num;
826 if (num > 5)
828 m_block = 2; // move to seconds
829 m_dirty = false;
831 else
832 m_dirty = true;
835 else // seconds
837 if (m_dirty) // have input the first digit
839 m_datetime.second *= 10;
840 m_datetime.second += num;
841 m_block = 0; // move to hours
842 m_dirty = false;
844 else // this is the first digit
846 m_datetime.second = num;
847 if (num > 5)
849 m_block = 0; // move to hours
850 m_dirty = false;
852 else
853 m_dirty = true;
858 void CGUIDialogNumeric::HandleInputTime(uint32_t num)
860 if (m_block == 0) // hour
862 if (m_dirty) // have input the first digit
864 if (m_datetime.hour < 2 || num < 4)
866 m_datetime.hour *= 10;
867 m_datetime.hour += num;
869 else
870 m_datetime.hour = num;
872 m_block = 1; // move to minutes
873 m_dirty = false;
875 else // this is the first digit
877 m_datetime.hour = num;
879 if (num > 2)
881 m_block = 1; // move to minutes
882 m_dirty = false;
884 else
885 m_dirty = true;
888 else // minute
890 if (m_dirty) // have input the first digit
892 m_datetime.minute *= 10;
893 m_datetime.minute += num;
894 m_block = 0; // move to hours
895 m_dirty = false;
897 else // this is the first digit
899 m_datetime.minute = num;
901 if (num > 5)
903 m_block = 0; // move to hours
904 m_dirty = false;
906 else
907 m_dirty = true;