Stav 23.06.2026

This commit is contained in:
2026-06-23 15:20:56 +02:00
commit 6d91e83e8c
5670 changed files with 1145969 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
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()