import tkinter as Tk from tkinter import ttk as Ttk from tkinter import font from pprint import pformat import threading from storage import readSave, save class FieldLabel(): """ Label to set alongside a text box. """ def __init__(self, parent, text, rowNum): self.widget = Ttk.Label(parent, text=text) self.widget.grid(row=rowNum, column=1, sticky='e') class EntryBox(): """ Basic entry box class. """ def __init__(self, parent, textVar=None): if textVar is None: self.textVar = Tk.StringVar() else: self.textVar = textVar self.widget = Ttk.Entry(parent, width=12, textvariable=self.textVar) class SavedEntryBox(EntryBox): """ Entry box that saves values to file with a given field name. Reads from that field on launch. """ def __init__(self, parent, fieldName, textVar, saveOnEnter=True, saveOnChange=False): self.textVar = textVar super().__init__(parent, self.textVar) self.fieldName = fieldName value = readSave(fieldName)[fieldName] if value is not None: self.textVar.set(value) else: self.textVar.set(fieldName) if saveOnEnter: self.widget.bind("", self.saveValue) if saveOnChange: self.textVar.trace_add("write", self.saveValue) def saveValue(self, *args): save({self.fieldName: self.textVar.get()}) class Container(): def __init__(self, parent, freezeCols=0): self.widget = Ttk.Frame(parent, padding=(3)) self.freezeCols = freezeCols def finalize(self): cols, rows = self.widget.grid_size() if self.freezeCols > 0: for i in range(self.freezeCols): self.widget.grid_columnconfigure(i, weight=0) for i in range(self.freezeCols, cols): self.widget.grid_columnconfigure(i, weight=1, uniform='column') for i in range(rows): self.widget.grid_rowconfigure(i, weight=0) class RequesterFrame(Container): """ Top-level frame for classes of manipulations. """ def __init__(self, parent, label): super().__init__(parent) self.widget.configure(height=480, width=330, borderwidth=3, relief="raised") self.widget.bind('', lambda e: self.widget.configure(relief="sunken")) self.widget.bind('', lambda e: self.widget.configure(relief="raised")) self.label = Ttk.Label(self.widget, text=label, font=font.nametofont('TkHeadingFont')) self.label.grid(row=0, column=0, sticky='nw') def finalize(self): cols, rows = self.widget.grid_size() self.widget.grid_columnconfigure(0, weight=0) self.widget.grid_columnconfigure(1, weight=0) self.widget.grid_columnconfigure(2, weight=1, minsize=150) for i in range(rows): self.widget.grid_rowconfigure(i, weight=1, minsize=5) class ApiButton(): """ Button which triggers an API call when clicked. """ def __init__(self, parent, label, rowNum, apiFunc, args): self.call = apiFunc self.args = args self.row = rowNum self.parent = parent self.widget = Ttk.Button(parent, command=self.pressed, text=label) self.widget.grid(row=rowNum, column=1, columnspan=2, sticky='nsew') def pressed(self, *args): progbar = Ttk.Progressbar(self.parent, orient='horizontal', mode='indeterminate', length=10) progbar.grid(row=self.row, column=0) threading.Thread(target=self.thread, args=(progbar,)).start() def thread(self, progbar): toPass = [] if isinstance(self.args, (list, tuple)): for arg in self.args: if type(arg) is Tk.StringVar: toPass.append(arg.get()) else: toPass.append(arg) else: if type(self.args) is Tk.StringVar: toPass.append(self.args.get()) else: toPass.append(self.args) self.resCode, self.resData = self.call(toPass) progbar.grid_forget() def formatResponse(resCode, resData): return f"""Response {resCode}: {pformat(resData)}"""