Files
KPK/loginscreen.py
T
2026-06-23 15:20:56 +02:00

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()