From 0f9ad0d0b810def89705d4c7fbbff962b16ba4c4 Mon Sep 17 00:00:00 2001 From: "B. Stack" Date: Tue, 24 Sep 2024 19:57:24 -0400 Subject: dpkg build recipe and assets --- fprintd_tk.py | 266 ---------------------------------------------------------- 1 file changed, 266 deletions(-) delete mode 100755 fprintd_tk.py (limited to 'fprintd_tk.py') 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("",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) - # 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() -- cgit