From 9ab441b6cfddb9ed459b3fc69c8ef0cf74e615fd Mon Sep 17 00:00:00 2001 From: "B. Stack" Date: Tue, 24 Sep 2024 14:10:12 -0400 Subject: add advanced pane which lets you control other users --- fprintd_tk.py | 69 +++++++++++++++++++++++++++++++++++++++++-------------- fprintd_tk_lib.py | 2 ++ 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/fprintd_tk.py b/fprintd_tk.py index 9af4513..492f2eb 100755 --- a/fprintd_tk.py +++ b/fprintd_tk.py @@ -6,7 +6,6 @@ # References: # stackrpms_tk.py # Improve: -# if user can control other users' fingerprints, then show a drop-down of users? import tkinter as tk, os, tkinter.simpledialog, sys, threading, time import tkstackrpms as stk @@ -34,11 +33,19 @@ for h in str_hands: class App(tk.Frame): def __init__(self, master): super().__init__(master) + # variables + self.statustext = tk.StringVar() + self.advanced = tk.BooleanVar(value=False) + self.advanced.trace_add("write",self.load_data_into_form) + self.current_username = os.getenv("USER") + self.username = tk.StringVar(value=self.current_username) + self.master.title("Gui for fprintd") imgicon = stk.get_scaled_icon("fingerprint-gui",24,"default", "","apps") self.master.tk.call("wm","iconphoto",self.master._w,imgicon) menu = tk.Menu(self.master) menu_file = tk.Menu(menu,tearoff=0) + menu_file.add_checkbutton(label="Advanced features", variable=self.advanced, underline=0) menu_file.add_command(label="Delete...", command=self.func_delete, underline=0) menu_file.add_separator() menu_file.add_command(label="Exit", command=self.func_exit, underline=1) @@ -50,9 +57,6 @@ class App(tk.Frame): self.grid() # use this instead of pack() self.background_color = self.master.cget("bg") - # statusbar variable - self.statustext = tk.StringVar() - # prepare finger images try: img_path + "" @@ -61,17 +65,27 @@ class App(tk.Frame): self.img_notenrolled = ImageTk.PhotoImage(stk.image_from_svg(os.path.join(img_path,"fingerprint-gui.svg"),32)) self.img_enrolled = ImageTk.PhotoImage(stk.image_from_svg(os.path.join(img_path,"fingerprint-enrolled.svg"),32)) + # advanced pane, top + self.frm_advanced = tk.Frame(self.master) + # start hidden + #self.frm_advanced.grid(row=0,column=0,columnspan=100) + tk.Label(self.frm_advanced,text="User").grid(row=0,column=0) + self.ent_username = stk.Entry(self.frm_advanced,textvariable=self.username,func=self.load_data_into_form) + self.ent_username.grid(row=0,column=1) + + # action pane, left side self.frm_actions = tk.Frame(self.master) - self.frm_actions.grid(row=0,column=0) + self.frm_actions.grid(row=1,column=0) self.action = tk.IntVar(value=1) self.last_fingerbutton_used = tk.StringVar() stk.Radiobutton(self.frm_actions,value=1,text="enroll",variable=self.action,underline=0).grid(row=0,column=0) stk.Radiobutton(self.frm_actions,value=2,text="verify",variable=self.action,underline=0).grid(row=1,column=0) + tk.Button(self.frm_actions,text="Refresh",underline=0,command=self.load_data_into_form).grid(row=2,column=0) # array of fingers # we want 2 rows, 5 columns self.frm_fingers = tk.Frame(self.master) - self.frm_fingers.grid(row=0,column=1) + self.frm_fingers.grid(row=1,column=1) self.fingers = [] hand = 0 while hand < 2: @@ -85,9 +99,10 @@ class App(tk.Frame): finger = finger + 1 hand = hand + 1 # because the underline business does not work on the radio button itself - # somehow the keypress takse over the lambda first var, so just set a dummy value, and pass our useful value as second parameter. + # somehow the keypress takes over the lambda first var, so just set a dummy value, and pass our useful value as second parameter. self.master.bind("",lambda a=1,b=1: self.set_action(a,b)) self.master.bind("",lambda a=1,b=2: self.set_action(a,b)) + self.master.bind("",self.load_data_into_form) # status bar stk.StatusBar(self.master,var=self.statustext) @@ -99,20 +114,38 @@ class App(tk.Frame): # this is used by Alt+E, Alt+V to select the radio buttons for enroll, verify, etc. self.action.set(a) - def load_data_into_form(self): + def get_used_user(self): + advanced = self.advanced.get() + if advanced: + used_user = self.username.get() + else: + used_user = self.current_username + return used_user + + def load_data_into_form(self, a = None, b = None, c = None): time.sleep(0.05) + advanced = self.advanced.get() + # show advanced toolbar + used_user = self.get_used_user() + if advanced: + print(f"DEBUG: showing advanced toolbar") + self.frm_advanced.grid(row=0,column=0,columnspan=100) + else: + print(f"DEBUG: hiding advanced toolbar") + self.frm_advanced.grid_forget() + # update enrolled fingers icons try: self.old_enrolled_fingers = self.enrolled_fingers except: # will happen if self.enrolled_fingers is not present self.old_enrolled_fingers = [] - temp1 = lib.get_enrolled_fingers() + temp1 = lib.get_enrolled_fingers(used_user) if temp1: self.enrolled_fingers = temp1 else: print(f"DEBUG (load_data_into_form): having to skip empty response from get_enrolled_fingers") - self.func_update_status("Unable to update enrolled fingers.") - print(f"DEBUG (load_data_into_form): got enrolled fingers {self.enrolled_fingers}") + self.func_update_status(f"Unable to read enrolled fingers for user {used_user}.", reload = False) + print(f"DEBUG (load_data_into_form): got user {used_user} enrolled fingers {self.enrolled_fingers}") for i in self.fingers: if str(i.cget('text')) in self.enrolled_fingers: i.config(image=self.img_enrolled) @@ -132,6 +165,7 @@ class App(tk.Frame): def func_finger_button(self, finger): print(f"DEBUG: func_finger_button finger {finger}, action {self.action.get()}") action = self.action.get() + used_user = self.get_used_user() # position in array is same as the value coming from radio button for actions. available_actions = ["none","enroll","verify"] try: @@ -141,7 +175,7 @@ class App(tk.Frame): if action_str in available_actions: self.last_fingerbutton_used.set(finger) try: - t1 = threading.Thread(target=lib.fprintd_action, args=(action_str, finger, self.func_update_status)) + t1 = threading.Thread(target=lib.fprintd_action, args=(action_str, finger, self.func_update_status, used_user)) t1.start() except Exception as e: self.statustext.set(e) @@ -152,7 +186,7 @@ class App(tk.Frame): # unfortunately useless here, because of the threading. #self.load_data_into_form() - def func_update_status(self, msg): + def func_update_status(self, msg, reload = True): msg = msg.strip() print(f"DEBUG (func_update_status): msg {msg}",file=sys.stderr) self.statustext.set(msg) @@ -184,13 +218,14 @@ class App(tk.Frame): if this_finger: stk.flash_entry(this_finger,["green",self.background_color]*3,300) break - self.load_data_into_form() + if reload: + self.load_data_into_form() def func_delete(self): - print(f"please ask user if he is certain to delete all enrolled fingerprints") - sure = tkinter.messagebox.askokcancel(title="Delete all enrolled fingerprints",message="Are you sure you want to delete all enrolled fingerprints?") + used_user = self.get_used_user() + sure = tkinter.messagebox.askokcancel(title="Delete all enrolled fingerprints",message=f"Are you sure you want to delete all enrolled fingerprints for user {used_user}?") if sure: - t1 = threading.Thread(target=lib.fprintd_action, args=("delete", "none", self.func_update_status)) + t1 = threading.Thread(target=lib.fprintd_action, args=("delete", "none", self.func_update_status, used_user)) t1.start() else: self.statustext.set("Cancelled the delete action.") diff --git a/fprintd_tk_lib.py b/fprintd_tk_lib.py index 6ecbed6..bc97448 100644 --- a/fprintd_tk_lib.py +++ b/fprintd_tk_lib.py @@ -21,6 +21,7 @@ def get_enrolled_fingers(user = None, verbose = False): enrolled_fingers = [] if user is None: user = _user + print(f"DEBUG (get_enrolled_fingers): user {user}") proc = subprocess.Popen( ["fprintd-list",user], stdout = subprocess.PIPE, @@ -51,6 +52,7 @@ def fprintd_action(action, finger, status_function = None, user = None, verbose if status_function: status_function(f"Invalid action {action}") return False + print(f"DEBUG (fprintd_action): command {command}") proc = subprocess.Popen( command, stdout = subprocess.PIPE, -- cgit