136 lines
4.4 KiB
Python
136 lines
4.4 KiB
Python
from kivy.uix.screenmanager import Screen
|
|
from kivy.uix.boxlayout import BoxLayout
|
|
from kivy.uix.label import Label
|
|
from kivy.metrics import dp
|
|
from kivy.logger import Logger
|
|
from kivy.app import App
|
|
from kivy.clock import Clock
|
|
|
|
from ui_utils import _popup_info
|
|
import numberpad
|
|
from kivy.uix.anchorlayout import AnchorLayout
|
|
from kivy.core.window import Window
|
|
|
|
MAX_LOGIN_FAILS = 3 # nebo treba 5
|
|
|
|
|
|
|
|
class LoginUserScreen(Screen):
|
|
def __init__(self, controller, on_success, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.fail_count = 0
|
|
self.controller = controller
|
|
self.on_success = on_success
|
|
root = BoxLayout(orientation="vertical")
|
|
self.lbl_info = Label(
|
|
text="Zadej PIN číšníka",
|
|
size_hint_y=None,
|
|
height=40,
|
|
)
|
|
self.lbl_error = Label(
|
|
text="",
|
|
color=(1, 0, 0, 1),
|
|
size_hint_y=None,
|
|
height=30,
|
|
)
|
|
root.add_widget(self.lbl_info)
|
|
root.add_widget(self.lbl_error)
|
|
self.center_layout = AnchorLayout(anchor_x="center", anchor_y="center")
|
|
root.add_widget(self.center_layout)
|
|
self.pad = None
|
|
self._keyboard_bound = False
|
|
self.add_widget(root)
|
|
|
|
def _on_key_down(self, window, key, scancode, codepoint, modifiers):
|
|
if self.manager and self.manager.current != self.name:
|
|
return False
|
|
if self.pad:
|
|
if key == 27:
|
|
self.pad._cancel()
|
|
return True # 🔥 zabráni zatvoreniu appky
|
|
if key in range(48, 58): # top row
|
|
self.pad._press(chr(key))
|
|
return True
|
|
elif key in range(256, 266): # numpad
|
|
self.pad._press(str(key - 256))
|
|
return True
|
|
elif chr(key)=='*' or key == 268:
|
|
self.pad._press("*")
|
|
return True
|
|
elif chr(key)=='.' or key == 266:
|
|
self.pad._press(".")
|
|
return True
|
|
elif key > 300:
|
|
print("pass")
|
|
pass
|
|
return True
|
|
elif codepoint and (codepoint.isalpha() or codepoint.isdigit()):
|
|
self.pad._press(codepoint)
|
|
return True
|
|
elif key == 8:
|
|
self.pad._press('⌫')
|
|
return True
|
|
elif key in (13, 40, 10, 271): # Enter / Numpad Enter
|
|
self.pad._accept()
|
|
return True
|
|
else:
|
|
return False
|
|
else:
|
|
return False
|
|
|
|
def on_enter(self):
|
|
self._bind_keyboard()
|
|
self.lbl_error.text = ""
|
|
if self.pad:
|
|
self.center_layout.remove_widget(self.pad)
|
|
self.pad = numberpad.NumberPad(
|
|
mode="code",
|
|
max_len=10,
|
|
on_accept=self._accept,
|
|
on_cancel=self._cancel,
|
|
)
|
|
self.pad.size_hint = (None, None)
|
|
self.pad.size = (dp(300), dp(400))
|
|
self.center_layout.add_widget(self.pad)
|
|
|
|
def on_leave(self):
|
|
self._unbind_keyboard()
|
|
if self.pad:
|
|
self.center_layout.remove_widget(self.pad)
|
|
self.pad = None
|
|
|
|
def _bind_keyboard(self):
|
|
if self._keyboard_bound:
|
|
return
|
|
Window.unbind(on_key_down=self._on_key_down)
|
|
Window.bind(on_key_down=self._on_key_down)
|
|
self._keyboard_bound = True
|
|
|
|
def _unbind_keyboard(self):
|
|
Window.unbind(on_key_down=self._on_key_down)
|
|
self._keyboard_bound = False
|
|
|
|
def _accept(self, pin: str):
|
|
try:
|
|
self.controller.login_user(pin)
|
|
# úspěch → reset čítače
|
|
self.fail_count = 0
|
|
Logger.info("LOGIN USER OK")
|
|
self.on_success()
|
|
except Exception as e:
|
|
self.fail_count += 1
|
|
Logger.warning(
|
|
f"LOGIN FAILED ({self.fail_count}): {type(e).__name__}: {e}"
|
|
)
|
|
self.pad.clear()
|
|
# příliš mnoho pokusů → konec aplikace
|
|
if self.fail_count >= MAX_LOGIN_FAILS:
|
|
Logger.error("MAX LOGIN FAILS REACHED")
|
|
_popup_info("Chyba", "Příliš mnoho chybných pokusů.\nAplikace bude ukončena.")
|
|
Clock.schedule_once(lambda *_: App.get_running_app().stop(), 2)
|
|
|
|
def _cancel(self):
|
|
# v POS obvykle znamená ukončení aplikace
|
|
Logger.info("LOGIN CANCEL")
|
|
App.get_running_app().stop()
|