import re import subprocess import sys from tkinter import Button, E, Entry, Label, OptionMenu, StringVar, Tk, W, messagebox from inqry.asset_qrcode import AssetQRCode from inqry.form_instructions import FormInstructions from inqry.system_specs.systemspecs import SystemSpecs class InQRyGUI: # TODO: Extract GUI attributes to methods def __init__(self): self.specs = SystemSpecs() self.form_instructions = FormInstructions(self.specs) self.asset_qr = AssetQRCode() self.root_window = Tk() self.root_window.title('InQRy') self.form_options_label = Label(self.root_window, text='Form Factor:') self.form_options_label.grid(row=1, column=1, sticky=E) self.form_options = tuple(self.form_instructions.form_types.keys())[0:2] self.form_selection = StringVar() self.form_selection.set(self.form_options[0]) self.form_menu = OptionMenu(self.root_window, self.form_selection, *self.form_options) self.form_menu.grid(row=1, column=2, sticky=W) self.qrcode_options_label = Label(self.root_window, text='QR Code Type:') self.qrcode_options_label.grid(row=2, column=1, sticky=E) self.qrcode_options = ['Create Asset', 'New Model'] self.qrcode_selection = StringVar() self.qrcode_selection.set(self.qrcode_options[0]) self.qrcode_menu = OptionMenu(self.root_window, self.qrcode_selection, *self.qrcode_options) self.qrcode_menu.grid(row=2, column=2, sticky=W) self.alias_label = Label(self.root_window, text='Alias:') self.alias_label.grid(row=3, column=1, sticky=E) self.alias_entry = Entry(self.root_window) self.alias_entry.grid(row=3, column=2) self.asset_tag_label = Label(self.root_window, text='Asset Tag:') self.asset_tag_label.grid(row=4, column=1, sticky=E) self.asset_tag_entry = Entry(self.root_window) self.asset_tag_entry.grid(row=4, column=2) # Instantiate the "Show" button for door-to-door inventory self.generate_qr_button = Button(self.root_window, text='Show QR Code', command=self.display) self.generate_qr_button.grid(row=5, column=1) self.generate_qr_button = Button(self.root_window, text='Save QR Code to Desktop', command=self.save) self.generate_qr_button.grid(row=5, column=2) def save(self): data = self.gather_user_input() try: filename = data[2] + '-' + data[1] except TypeError: filename = data[3] + '-' + data[0] try: return self.asset_qr.save(filename, self.form_instructions.gui_helper(*data)) except TypeError: print('Improper formatting.') except FileExistsError: error_message_box('File already exists.') def display(self): data = self.gather_user_input() return self.asset_qr.display(self.form_instructions.gui_helper(*data)) def gather_user_input(self) -> tuple: if self.qrcode_selection.get() == 'New Model': return self.qrcode_selection.get(), None, None, self.form_selection.get() return self.qrcode_selection.get(), self.get_asset_tag(), self.get_alias(), self.form_selection.get() def _validate_field_contents(self, contents, field): patterns = {'Alias': (re.compile(r'^(v\-)?[A-Za-z]+$'), 'The Alias has to be a v- followed by more then one letter. The v- can be ommited.'), 'Asset Tag': (re.compile(r'^E?\d{7}$'), 'The Asset Tag has to be an E followed by 7 numbers. The E can be ommited.')} validator, human_readable = patterns[field] if bool(re.match(validator, contents)): return contents error_message = '{} is not properly formatted.'.format(field) error_message_box(error_message) raise ValueError(error_message) def get_alias(self): return self._validate_field_contents(self.alias_entry.get(), 'Alias') def get_asset_tag(self): return self._validate_field_contents(self.asset_tag_entry.get(), 'Asset Tag') def obtain_default_dimensions_for_the_root_gui_object(self): return tuple(int(_) for _ in self.root_window.geometry().split('+')[0].split('x')) def calculate_center_coordinates(self, screen_dimension, current_dimension): return (screen_dimension // 2) - (current_dimension // 2) def center(self): self.root_window.update_idletasks() size = self.obtain_default_dimensions_for_the_root_gui_object() height = size[0] width = size[1] x = self.calculate_center_coordinates(self.root_window.winfo_screenwidth(), height) y = self.calculate_center_coordinates(self.root_window.winfo_screenheight(), width) self.root_window.geometry('{}x{}+{}+{}'.format(height, width, x, y)) def error_message_box(message: str): messagebox.showerror('Oops!', message) def mobile_capability(): # TODO: Re-implement mobile_capability() into GUI if sys.platform == 'darwin': try: subprocess.check_output(['/usr/local/bin/cfgutil']) return 'active' except FileNotFoundError: print( ''' No such file or directory: "/usr/local/bin/cfgutil" You must install cfgutil using Apple Configurator in order to use InQRy with a mobile device. ''' ) return 'disable' else: pass