aboutsummaryrefslogtreecommitdiff
path: root/fprintd_tk.py
diff options
context:
space:
mode:
authorB. Stack <bgstack15@gmail.com>2024-09-24 19:57:24 -0400
committerB. Stack <bgstack15@gmail.com>2024-09-24 19:57:24 -0400
commit0f9ad0d0b810def89705d4c7fbbff962b16ba4c4 (patch)
tree3061220ed78cfe4f4c137e5973c451dd307f1bca /fprintd_tk.py
parentadd image to readme (diff)
downloadfprintd-tk-master.tar.gz
fprintd-tk-master.tar.bz2
fprintd-tk-master.zip
dpkg build recipe and assetsHEADmaster
Diffstat (limited to 'fprintd_tk.py')
-rwxr-xr-xfprintd_tk.py266
1 files changed, 0 insertions, 266 deletions
diff --git a/fprintd_tk.py b/fprintd_tk.py
deleted file mode 100755
index f7442d8..0000000
--- a/fprintd_tk.py
+++ /dev/null
@@ -1,266 +0,0 @@
-#!/usr/bin/env python3
-# File: fprintd_tk.py
-# Location: https://bgstack15.cgit/fprintd-tk
-# Author: bgstack15
-# Startdate: 2024-09-22-1 14:26
-# SPDX-License-Identifier: GPL-3.0-only
-# Title: Gui for fprintd
-# Purpose: tkinter desktop gui app for management fingerprint enrollments
-# Project: fprintd-tk
-# History:
-# Usage:
-# Run from window manager application menu
-# Reference:
-# stackrpms_tk.py
-# Improve:
-# Dependencies:
-# dep-devuan: python3-tkstackrpms, python3-tk, python3-pil
-# fprintd_tk_lib.py
-# Documentation:
-# README.md
-
-import tkinter as tk, os, tkinter.simpledialog, sys, threading, time
-import tkstackrpms as stk
-import fprintd_tk_lib as lib
-from PIL import Image, ImageTk
-
-ABOUT_TEXT = """
-fprintd_tk \"Gui for fprintd\"
-(C) 2024 bgstack15
-SPDX-License-Identifier: GPL-3.0-only
-Icons adapted from Numix-Icon-Theme-Circle (GPL 3)
-"""
-
-# configurable by admin or installation
-img_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),"images")
-
-# These will be used a lot in the program.
-str_hands = ["left","right"]
-str_fingers = ["thumb","index-finger","middle-finger","ring-finger","little-finger"]
-str_all = []
-for h in str_hands:
- for f in str_fingers:
- str_all.append(f"{h}-{f}")
-
-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.verbose = tk.BooleanVar(value=False)
-
- 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, state="disabled")
- menu_file.add_checkbutton(label="Verbose", variable=self.verbose, 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)
- menu.add_cascade(label="File",menu=menu_file,underline=0)
- menu_help = tk.Menu(menu,tearoff=0)
- menu_help.add_command(label="About", command=self.func_about, underline=0)
- menu.add_cascade(label="Help",menu=menu_help,underline=0)
- self.master.config(menu=menu)
- self.grid() # use this instead of pack()
- self.background_color = self.master.cget("bg")
-
- # prepare finger images
- try:
- img_path + ""
- except:
- img_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),"images")
- 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=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=1,column=1)
- self.fingers = []
- hand = 0
- while hand < 2:
- finger = 0
- while finger < 5:
- fnum = finger if hand==1 else len(str_fingers)-finger-1
- #print(f"While preparing hand {hand}, evaluating finger {finger}, which might need to be number {fnum}")
- tf = str_hands[hand] + "-" + str_fingers[fnum]
- self.fingers.append(tk.Button(self.frm_fingers,text=tf,padx=0,pady=0,command=lambda f=tf: self.func_finger_button(f),image=self.img_notenrolled,compound="top"))
- self.fingers[-1].grid(row=hand,column=finger)
- finger = finger + 1
- hand = hand + 1
- # because the underline business does not work on the radio button itself
- # 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("<Alt-e>",lambda a=1,b=1: self.set_action(a,b))
- self.master.bind("<Alt-v>",lambda a=1,b=2: self.set_action(a,b))
- self.master.bind("<Alt-r>",self.load_data_into_form)
-
- # status bar
- stk.StatusBar(self.master,var=self.statustext)
- # check if user has setusername polkit-1 permission, which lets him control fingerprint enrollments for other users.
- temp1 = lib.check_setusername_permission(self.func_update_status)
- if self.verbose.get():
- print(f"DEBUG (init): has set_username: {temp1}")
- if temp1:
- #self.chk_advanced.configure(state="enabled")
- #menu_file.child[0].child[0].configure(state="enabled")
- menu_file.entryconfigure(0,state="normal")
- #print(menu_file.children)
- # and now, load data into form for the first time
- self.load_data_into_form()
-
- def set_action(self, keypress, a):
- #print(f"DEBUG: got keypress {keypress}, a={a}")
- # this is used by Alt+E, Alt+V to select the radio buttons for enroll, verify, etc.
- self.action.set(a)
-
- 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:
- if self.verbose.get():
- print(f"DEBUG: showing advanced toolbar")
- self.frm_advanced.grid(row=0,column=0,columnspan=100)
- else:
- if self.verbose.get():
- 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(used_user)
- if temp1:
- self.enrolled_fingers = temp1
- else:
- if self.verbose.get():
- print(f"DEBUG (load_data_into_form): having to skip empty response from get_enrolled_fingers")
- self.func_update_status(f"Unable to read enrolled fingers for user {used_user}.", reload = False)
- if self.verbose.get():
- 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)
- else:
- i.config(image=self.img_notenrolled)
-
- # functions
- def func_about(self):
- """ Display about dialog. """
- tk.messagebox.Message(title="About",message=ABOUT_TEXT,icon="info").show()
-
- def func_exit(self):
- # in case we need to manually do stuff
- # otherwise command=self.client_exit would have sufficed.
- self.master.quit()
-
- def func_finger_button(self, finger):
- if self.verbose.get():
- 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:
- action_str = available_actions[action]
- except ValueError:
- action_str = "OFF"
- 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, used_user))
- t1.start()
- except Exception as e:
- self.statustext.set(e)
- else:
- self.statustext.set(f"Invalid action {action}, string {action_str}.")
- # This blocks everything! Do not use this.
- #t1.join()
- # unfortunately useless here, because of the threading.
- #self.load_data_into_form()
-
- def func_update_status(self, msg, reload = True):
- msg = msg.strip()
- if self.verbose.get():
- print(f"DEBUG (func_update_status): msg {msg}",file=sys.stderr)
- self.statustext.set(msg)
- try:
- this_finger = [i for i in self.fingers if i.cget("text") == self.last_fingerbutton_used.get()][0]
- except Exception as e:
- this_finger = None
- if self.verbose.get():
- print(f"DEBUG (func_update_status): while evaluating last-used finger, got {e}")
- # flash these red
- failure_messages = [
- "enroll-duplicate",
- "verify-no-match"
- ]
- # flash these green
- success_messages = [
- "verify-match",
- "enroll-completed"
- ]
- flashed = False
- for i in failure_messages:
- if i in msg:
- flashed = True
- if this_finger:
- stk.flash_entry(this_finger,["red",self.background_color]*3,300)
- break
- if not flashed:
- for i in success_messages:
- if i in msg:
- if this_finger:
- stk.flash_entry(this_finger,["green",self.background_color]*3,300)
- break
- if reload:
- self.load_data_into_form()
-
- def func_delete(self):
- 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, used_user))
- t1.start()
- else:
- self.statustext.set("Cancelled the delete action.")
-
-# main
-root = tk.Tk()
-fprintd_tk = App(root)
-fprintd_tk.mainloop()
bgstack15