def add_link(self): def ok(eveny=None): lien = link.get() txt = text.get() if lien: if not txt: txt = lien self.nb_links += 1 if self.txt.tag_ranges("sel"): index = self.txt.index("sel.first") self.txt.delete('sel.first', 'sel.last') else: index = "current" tags = self.txt.tag_names(index) + ("link", "link#%i" % self.nb_links) self.txt.insert("current", txt, tags) if not lien[:4] == "http": lien = "http://" + lien self.links[self.nb_links] = lien self.txt.tag_bind("link#%i" % self.nb_links, "<Button-1>", lambda e: open_url(lien)) top.destroy() top = Toplevel(self) top.transient(self) top.update_idletasks() top.geometry("+%i+%i" % top.winfo_pointerxy()) top.grab_set() top.resizable(True, False) top.title(_("Link")) top.columnconfigure(1, weight=1) text = Entry(top) link = Entry(top) if self.txt.tag_ranges('sel'): txt = self.txt.get('sel.first', 'sel.last') else: txt = '' text.insert(0, txt) text.icursor("end") Label(top, text=_("Text")).grid(row=0, column=0, sticky="e", padx=4, pady=4) Label(top, text=_("Link")).grid(row=1, column=0, sticky="e", padx=4, pady=4) text.grid(row=0, column=1, sticky="ew", padx=4, pady=4) link.grid(row=1, column=1, sticky="ew", padx=4, pady=4) Button(top, text="Ok", command=ok).grid(row=2, columnspan=2, padx=4, pady=4) text.focus_set() text.bind("<Return>", ok) link.bind("<Return>", ok)
class ListDialog(object): def __init__ (self, master, items, message, accept_func): self.accept_func = accept_func self.top = Toplevel(master) self.top.transient(master) self.top.rowconfigure(0, weight=1) self.top.rowconfigure(1, weight=3) self.top.rowconfigure(2, weight=0) self.top.columnconfigure(0, weight=1) self.top.columnconfigure(1, weight=1) self.top.resizable(width=True, height=True) self.frame = Frame(self.top) self.frame.rowconfigure(0, weight=1) self.frame.rowconfigure(1, weight=0) self.frame.columnconfigure(0, weight=1) self.frame.columnconfigure(1, weight=0) self.frame.grid(row=0, column=0, sticky=(N, S, W, E), columnspan=2) self.canvas = Canvas(self.frame) self.canvas.create_text(0, 0, text=message, anchor=NW) self.canvas.grid(row=0, column=0, sticky=(N, W, S, E)) self.vscroll = Scrollbar(self.frame, command=self.canvas.yview) self.vscroll.grid(row=0, column=1, sticky=(N, S)) self.canvas['yscrollcommand'] = self.vscroll.set self.hscroll = Scrollbar(self.frame, command=self.canvas.xview, orient=HORIZONTAL) self.hscroll.grid(row=1, column=0, sticky=(W, E), columnspan=2) self.canvas['xscrollcommand'] = self.hscroll.set self.canvas['scrollregion'] = self.canvas.bbox('all') self.canvas.bind('<Button-4>', self.scroll) self.canvas.bind('<Button-5>', self.scroll) self.canvas.bind('<MouseWheel>', self.scroll) self.view = NameView(self.top, sorted(items)) self.view.widget.grid(row=1, column=0, columnspan=2, sticky=(N, W, E, S)) self.delbutton = Button(self.top, text='Ok', command=self.accept ) self.cancelbutton = Button(self.top, text='Cancel', command=self.cancel) self.delbutton.grid(row=2, column=0) self.cancelbutton.grid(row=2, column=1) self.view.widget.focus_set() def accept(self): self.accept_func(self.view.selection()) self.top.destroy() def cancel(self): self.result = None self.top.destroy() def scroll(self, event): if event.num == 4 or event.delta > 0: self.canvas.yview(SCROLL, -1, UNITS) elif event.num == 5 or event.delta < 0: self.canvas.yview(SCROLL, 1, UNITS)
def displayError (error): errorWindow = Toplevel(master=mainWindow, bg='#0a154a') errorWindow.title("Busbar calculation error!") errorWindow.rowconfigure(0, weight=1, minsize=20) errorWindow.columnconfigure(0, weight=1, minsize=20) errorWindow.columnconfigure(1, weight=1, minsize=20) errorText = tk.Label(master=errorWindow, text=error, font=("Helvetica", 9), bg='#0a154a', fg="white") errorIcon = tk.Label(master=errorWindow, image=errorIconFile, bg='#0a154a') errorIcon.grid(row=0, column=0, sticky="w", padx=(30,0)) errorText.grid(row=0, column=1, sticky="e", padx=(0,30), pady=40)
class SpeciesListDialog(): def __init__(self, parent): self.parent = parent self.gui = Toplevel(parent.guiRoot) self.gui.grab_set() self.gui.focus() self.gui.columnconfigure(0, weight=1) self.gui.rowconfigure(1, weight=1) Label(self.gui, text="Registered Species:").grid(row=0, column=0, pady=5, padx=5, sticky="w") self.listRegisteredSpecies = Listbox(self.gui, width=70) self.buttonAdd = Button(self.gui, text=" + ") self.buttonDel = Button(self.gui, text=" - ") self.listRegisteredSpecies.grid(row=1, column=0, columnspan=3, sticky="nswe", pady=5, padx=5) self.buttonAdd.grid(row=2, column=1, pady=5, padx=5) self.buttonDel.grid(row=2, column=2, pady=5, padx=5) # Set (minimum + max) Window size self.gui.update() self.gui.minsize(self.gui.winfo_width(), self.gui.winfo_height()) # self.gui.maxsize(self.gui.winfo_width(), self.gui.winfo_height()) self.actionUpdate(None) self.gui.bind("<<Update>>", self.actionUpdate) self.gui.protocol("WM_DELETE_WINDOW", self.actionClose) self.buttonDel.bind("<ButtonRelease>", self.actionDel) self.buttonAdd.bind("<ButtonRelease>", self.actionAdd) self.gui.mainloop() def actionClose(self): self.parent.guiRoot.event_generate("<<Update>>", when="tail") self.gui.destroy() def actionUpdate(self, event): self.listRegisteredSpecies.delete(0, "end") for (taxid, name) in self.parent.optimizer.speciesList: self.listRegisteredSpecies.insert("end", taxid + ": " + name) def actionDel(self, event): try: selection = self.listRegisteredSpecies.selection_get() selectionSplit = selection.split(": ") self.parent.optimizer.speciesList.remove((selectionSplit[0], selectionSplit[1])) self.gui.event_generate("<<Update>>") except tkinter.TclError : # no selection pass def actionAdd(self, Event): SpeciesSearchDialog(self.parent, self)
class AddWriteWindow: def __init__(self, parent, model): self.buf_type = tk.IntVar() self.model = model self.parent = parent self.window = Toplevel(parent.window) self.window.title('Dodaj test write') self.window.geometry('300x320') self.window.columnconfigure(2, weight=1) self.window.rowconfigure(4, weight=1) Label(self.window, text='Parametr count').grid(sticky=tk.NW) self.count_entry = Entry(self.window) self.count_entry.grid(row=0, column=1, sticky=tk.NW) Radiobutton(self.window, text='Bufor znakowy', variable=self.buf_type, value=0).grid(row=2, column=0, sticky=tk.NW) Radiobutton(self.window, text='Bufor bajtów (hex)', variable=self.buf_type, value=1).grid(row=2, column=1, sticky=tk.NW) Label(self.window, text='Zawartość bufora').grid(row=3, sticky=tk.NW) self.buffer_entry = Text(self.window, width=36, height=12) self.buffer_entry.grid(row=4, columnspan=3, sticky=tk.NW + tk.E + tk.S, padx=5) Button(self.window, text='Dodaj', command=self.add_case).grid(row=5, columnspan=2) self.window.transient(master=parent.window) self.window.grab_set() def add_case(self): text = self.buffer_entry.get("1.0", tk.END).strip() try: if self.buf_type.get() == 0: self.model.corpus.add_case( struct.pack('Q{}s'.format(len(text.encode())), int(self.count_entry.get()), text.encode()), 'write') else: print(str(text)) buf_bytes = bytes.fromhex(str(text)) print(buf_bytes) self.model.corpus.add_case( struct.pack('Q{}s'.format(len(buf_bytes)), int(self.count_entry.get()), buf_bytes), 'write') self.destroy() except ValueError: messagebox.showinfo("Błąd", "Podano złą wartość argumentu") def destroy(self): self.window.grab_release() self.window.destroy()
class NewProjectWindow: def __init__(self, parent, model): self.model = model self.parent = parent self.window = Toplevel(parent.window) self.window.title('Nowy projekt') self.window.geometry('600x90') self.window.rowconfigure(0, weight=1) self.window.rowconfigure(1, weight=1) self.window.columnconfigure(1, weight=1) Label(self.window, text='Nazwa projektu:').grid(row=0, sticky=tk.NW + tk.N + tk.S) self.name_entry = Entry(self.window) self.name_entry.grid(row=0, column=1, columnspan=2, sticky=tk.NW + tk.N + tk.S + tk.E) Label(self.window, text='Ścieżka do projektu:').grid(row=1, column=0, sticky=tk.NW + tk.N + tk.S) self.path_label = Label(self.window, anchor=tk.W, bg='white', width=40) self.path_label.grid(row=1, column=1, sticky=tk.NW + tk.N + tk.S + tk.E) Button(self.window, text='Wybierz', command=self.pick_dir).grid(row=1, column=2, sticky=tk.NW + tk.N + tk.S) Button(self.window, text='Anuluj', command=self.destroy).grid(row=2, column=0, sticky=tk.NW + tk.N + tk.S + tk.E) Button(self.window, text='Stwórz', command=self.create).grid(row=2, column=2, sticky=tk.NW + tk.N + tk.S + tk.E) def pick_dir(self): options = {} options['defaultextension'] = '.afz' options['filetypes'] = [('Pliki projektu', '.afz'), ('Wszystkie pliki', '.*')] options['title'] = 'Utwórz projekt' filename = filedialog.asksaveasfilename(**options) self.path_label.config(text=filename) def create(self): self.model.new_project(self.path_label['text'], self.name_entry.get()) self.destroy() def destroy(self): self.window.destroy()
class AddRestrictionDialog(): def __init__(self, parent): self.parent = parent self.gui = Toplevel(parent.guiRoot) self.gui.grab_set() self.gui.focus() self.gui.columnconfigure(0, weight=1) self.gui.columnconfigure(1, weight=1) Label(self.gui, text="Enzyme:").grid(row=0, column=0, sticky="e", padx=5) self.entryEnzyme = Entry(self.gui) self.entryEnzyme.grid(row=0, column=1, sticky="w", padx=5, pady=10) self.frameButtonGroup = Frame(self.gui) self.frameButtonGroup.grid(row=1, column=0, columnspan=2, pady=10) self.buttonOK = Button(self.frameButtonGroup, text=" OK ") self.buttonCancel = Button(self.frameButtonGroup, text=" Cancel ") self.buttonOK.grid(row=0, column=1, sticky="w", padx=5) self.buttonCancel.grid(row=0, column=0, sticky="e", padx=5) # Set (minimum + max) Window size self.gui.update() self.gui.minsize(self.gui.winfo_width(), self.gui.winfo_height()) self.gui.maxsize(self.gui.winfo_width(), self.gui.winfo_height()) self.entryEnzyme.focus() self.buttonOK.bind("<ButtonRelease>", self.actionOK) self.buttonCancel.bind("<ButtonRelease>", self.actionCancel) self.entryEnzyme.bind("<Return>", self.actionOK) self.gui.mainloop() # self.gui.grab_release() # self.gui.destroy() def actionOK(self, event): enzymeString = self.entryEnzyme.get() if enzymeString in rest_dict.keys(): if enzymeString in self.parent.optimizer.restrictionEnzymeList: showinfo("", (enzymeString + " was already added to the list")) return self.parent.optimizer.restrictionEnzymeList.append(enzymeString) self.parent.guiRoot.event_generate("<<Update>>", when="tail") self.gui.destroy() else: showinfo("", (enzymeString + " is not a valid restriction enzyme")) def actionCancel(self, event): self.gui.destroy()
class AddRestrictionDialog: def __init__(self, parent): self.parent = parent self.gui = Toplevel(parent.guiRoot) self.gui.grab_set() self.gui.focus() self.gui.columnconfigure(0, weight=1) self.gui.columnconfigure(1, weight=1) Label(self.gui, text="Enzyme:").grid(row=0, column=0, sticky="e", padx=5) self.entryEnzyme = Entry(self.gui) self.entryEnzyme.grid(row=0, column=1, sticky="w", padx=5, pady=10) self.frameButtonGroup = Frame(self.gui) self.frameButtonGroup.grid(row=1, column=0, columnspan=2, pady=10) self.buttonOK = Button(self.frameButtonGroup, text=" OK ") self.buttonCancel = Button(self.frameButtonGroup, text=" Cancel ") self.buttonOK.grid(row=0, column=1, sticky="w", padx=5) self.buttonCancel.grid(row=0, column=0, sticky="e", padx=5) # Set (minimum + max) Window size self.gui.update() self.gui.minsize(self.gui.winfo_width(), self.gui.winfo_height()) self.gui.maxsize(self.gui.winfo_width(), self.gui.winfo_height()) self.entryEnzyme.focus() self.buttonOK.bind("<ButtonRelease>", self.actionOK) self.buttonCancel.bind("<ButtonRelease>", self.actionCancel) self.entryEnzyme.bind("<Return>", self.actionOK) self.gui.mainloop() # self.gui.grab_release() # self.gui.destroy() def actionOK(self, event): enzymeString = self.entryEnzyme.get() if enzymeString in rest_dict.keys(): if enzymeString in self.parent.optimizer.restrictionEnzymeList: showinfo("", (enzymeString + " was already added to the list")) return self.parent.optimizer.restrictionEnzymeList.append(enzymeString) self.parent.guiRoot.event_generate("<<Update>>", when="tail") self.gui.destroy() else: showinfo("", (enzymeString + " is not a valid restriction enzyme")) def actionCancel(self, event): self.gui.destroy()
class DriversWindow: def __init__(self, parent, model): self.model = model self.parent = parent self.window = Toplevel(parent.window) self.window.title('Lista sterowników') self.window.geometry('600x400') self.window.rowconfigure(0, weight=1) self.window.columnconfigure(0, weight=1) self.x_scroll = Scrollbar(self.window, orient=tk.HORIZONTAL) self.y_scroll = Scrollbar(self.window, orient=tk.VERTICAL) self.x_scroll.grid(row=1, column=0, columnspan=2, sticky=tk.E + tk.W) self.y_scroll.grid(row=0, column=2, sticky=tk.N + tk.S) self.listbox = Listbox(self.window, xscrollcommand=self.x_scroll.set, yscrollcommand=self.y_scroll.set) self.x_scroll['command'] = self.listbox.xview self.y_scroll['command'] = self.listbox.yview threading.Thread(target=self.populate_list).start() self.prog_window = ProgressWindow(self, 'Trwa szukanie sterowników') self.prog_window.start() self.listbox.grid(row=0, column=0, sticky=tk.N + tk.E + tk.S + tk.W, columnspan=2) Button(self.window, text='Wybierz', command=self.pick_dev).grid(row=2, sticky=tk.NE, padx=10) Button(self.window, text='Anuluj', command=self.destroy).grid(row=2, column=1, sticky=tk.NW, padx=10) self.window.transient(master=parent.window) def pick_dev(self): self.model.project.devpath = self.listbox.get( self.listbox.curselection()).split()[-1] self.parent.refresh_driver() self.destroy() def populate_list(self): dev_list = self.model.list_dev_paths() for d in dev_list: if d is not '': self.listbox.insert(tk.END, d) self.prog_window.destroy() self.window.grab_set() def destroy(self): self.window.grab_release() self.window.destroy()
class GeneratorWindow: def __init__(self, parent, model): self.model = model self.parent = parent self.window = Toplevel(parent.window) self.window.title('Generator') self.window.geometry('600x400') self.window.transient(master=parent.window) self.tabs = Notebook(self.window) self.ioctl_frame = Frame(self.tabs) self.write_frame = Frame(self.tabs) self.mmap_frame = Frame(self.tabs) self.tabs.add(self.ioctl_frame, text='ioctl') self.tabs.add(self.write_frame, text='write') self.tabs.add(self.mmap_frame, text='mmap') self.window.rowconfigure(0, weight=1) self.window.columnconfigure(0, weight=1) self.tabs.grid(sticky=tk.NW + tk.S + tk.E) self.window.grab_set() def destroy(self): self.window.grab_release() self.window.destroy()
def show_stat(self): """ show best times """ def reset(): """ reset best times """ for level in ["easy", "medium", "difficult"]: CONFIG.set("Statistics", level, "") top.destroy() if self.chrono_on: self.play_pause() top = Toplevel(self) top.transient(self) top.columnconfigure(1, weight=1) top.resizable(0, 0) top.title(_("Statistics")) top.grab_set() Label(top, text=_("Best times"), font="Sans 12 bold").grid(row=0, columnspan=2, padx=30, pady=10) for i, level in enumerate(["easy", "medium", "difficult"]): Label(top, text=_(level.capitalize()), font="Sans 10 bold").grid(row=i + 1, column=0, padx=(20, 4), pady=4, sticky="e") tps = CONFIG.get("Statistics", level) if tps: tps = int(tps) m = tps // 60 s = tps % 60 Label(top, text=" %i min %i s" % (m, s), font="Sans 10").grid(row=i + 1, column=1, sticky="w", pady=4, padx=(4, 20)) Button(top, text=_("Close"), command=top.destroy).grid(row=4, column=0, padx=(10, 4), pady=10) Button(top, text=_("Clear"), command=reset).grid(row=4, column=1, padx=(4, 10), pady=10)
def treeVisualCall(treeLevelNodeToBucNodeDict, treeSequence): mainWindow = Toplevel() mainWindow.geometry('1080x720+150+10') mainWindow.resizable(0, 0) cols = 31 levels = 10 numberOfParentChildren = 2 mainWindow.title('Tree Visualization') mainWindow.state('zoomed') mainCanvas = tkinter.Canvas(mainWindow, width=300, height=200, bg="bisque2") mainCanvas.pack(expand=1, fill=BOTH) nodeGridPosition = dict() nodeDict = {} edgeList = list() edgeDict = dict() frameList = [[] for i in range(levels)] labelList = [[] for i in range(levels)] # Adjusting row weight for Main window and Canvas for i in range(levels): mainCanvas.rowconfigure(i, weight=2) mainWindow.rowconfigure(i, weight=2) for i in range(cols): mainCanvas.columnconfigure(i, weight=1) mainWindow.columnconfigure(i, weight=1) # def updatePos(): for i in range(len(edgeList)): mainCanvas.coords(edgeList[i], edgeDict[i][0].winfo_x() , edgeDict[i][0].winfo_y() , edgeDict[i][1].winfo_x() , edgeDict[i][1].winfo_y()) becNodeToGridLabelDict = dict() def delayNode(becToDsNode): lbl = tkinter.Label(mainCanvas, borderwidth=4, relief='solid', height=2, width=2, text=becToDsNode.tree, padx='2', pady='2') xCord = becToDsNode.x * 2 becNodeToGridLabelDict[becToDsNode] = lbl lbl.grid(row=int(becToDsNode.y), column=int(xCord) + 13) mainWindow.update() if becToDsNode.parent == None: return else: delayEdge(becNodeToGridLabelDict[becToDsNode.parent], becNodeToGridLabelDict[becToDsNode]) # updatePos() # mainWindow.update() updatePos() mainWindow.update() lbll = tkinter.Label() lbll.winfo_rootx() def delayEdge(startNode, endNode): mainWindow.update() slope = ((endNode.winfo_y()) - startNode.winfo_y()) / ((endNode.winfo_x()) - startNode.winfo_x() + 1) print(slope) newEdge = mainCanvas.create_line(startNode.winfo_x() + 1, startNode.winfo_y() + 1, startNode.winfo_x() + 1, startNode.winfo_y() + 1, arrow=tkinter.LAST) mainWindow.update() print(startNode.winfo_x(), startNode.winfo_y(), endNode.winfo_x(), endNode.winfo_y()) edgeList.append(newEdge) edgeDict[len(edgeList) - 1] = list() edgeDict[len(edgeList) - 1].append(startNode) edgeDict[len(edgeList) - 1].append(endNode) mainWindow.update() for y_anim in range(startNode.winfo_y(), endNode.winfo_y(), 3): # mainWindow.update() x_anim = (endNode.winfo_x()) - (((endNode.winfo_y()) - y_anim) / (slope)) # print(startNode.winfo_x(), startNode.winfo_y(), # endNode.winfo_x(), # endNode.winfo_y()) mainCanvas.coords(newEdge, startNode.winfo_x() + 2, startNode.winfo_y(), x_anim, y_anim, ) mainWindow.update() updatePos() # def drawTree(delayTime, treeseq): for i in range(len(treeseq)): mainCanvas.after(delayTime, delayNode(treeLevelNodeToBucNodeDict[treeSequence[i]])) mainWindow.update() drawTree(500, treeSequence)
class ListDialog(object): def __init__(self, master, items, message, accept_func): self.accept_func = accept_func self.top = Toplevel(master) self.top.transient(master) self.top.rowconfigure(0, weight=1) self.top.rowconfigure(1, weight=3) self.top.rowconfigure(2, weight=0) self.top.columnconfigure(0, weight=1) self.top.columnconfigure(1, weight=1) self.top.resizable(width=True, height=True) self.frame = Frame(self.top) self.frame.rowconfigure(0, weight=1) self.frame.rowconfigure(1, weight=0) self.frame.columnconfigure(0, weight=1) self.frame.columnconfigure(1, weight=0) self.frame.grid(row=0, column=0, sticky=(N, S, W, E), columnspan=2) self.canvas = Canvas(self.frame) self.canvas.create_text(0, 0, text=message, anchor=NW) self.canvas.grid(row=0, column=0, sticky=(N, W, S, E)) self.vscroll = Scrollbar(self.frame, command=self.canvas.yview) self.vscroll.grid(row=0, column=1, sticky=(N, S)) self.canvas['yscrollcommand'] = self.vscroll.set self.hscroll = Scrollbar(self.frame, command=self.canvas.xview, orient=HORIZONTAL) self.hscroll.grid(row=1, column=0, sticky=(W, E), columnspan=2) self.canvas['xscrollcommand'] = self.hscroll.set self.canvas['scrollregion'] = self.canvas.bbox('all') self.canvas.bind('<Button-4>', self.scroll) self.canvas.bind('<Button-5>', self.scroll) self.canvas.bind('<MouseWheel>', self.scroll) self.view = NameView(self.top, sorted(items)) self.view.widget.grid(row=1, column=0, columnspan=2, sticky=(N, W, E, S)) self.delbutton = Button(self.top, text='Ok', command=self.accept) self.cancelbutton = Button(self.top, text='Cancel', command=self.cancel) self.delbutton.grid(row=2, column=0) self.cancelbutton.grid(row=2, column=1) self.view.widget.focus_set() def accept(self): self.accept_func(self.view.selection()) self.top.destroy() def cancel(self): self.result = None self.top.destroy() def scroll(self, event): if event.num == 4 or event.delta > 0: self.canvas.yview(SCROLL, -1, UNITS) elif event.num == 5 or event.delta < 0: self.canvas.yview(SCROLL, 1, UNITS)
class SpeciesSearchDialog(): def __init__(self, parent, caller): # main window self.parent=parent # dialog that called this second dialog self.caller=caller self.gui = Toplevel(parent.guiRoot) self.gui.grab_set() self.gui.focus() self.gui.columnconfigure(0, weight=1) self.gui.rowconfigure(1, weight=1) self.entrySearch = Entry(self.gui) self.buttonSearch = Button(self.gui, text=" Search ") self.buttonAdd = Button(self.gui, text=" Add Species ") self.buttonClose = Button(self.gui, text=" Close Window ") self.frameResults = Frame(self.gui) self.frameResults.columnconfigure(0, weight=1) self.frameResults.rowconfigure(0, weight=1) self.scrollResults = Scrollbar(self.frameResults, orient="vertical") self.scrollResults.grid(row=0, column=1, sticky="ns") self.listResults = Listbox(self.frameResults, width=70, height=20) self.listResults.grid(row=0, column=0, sticky="nswe") self.listResults.config(yscrollcommand=self.scrollResults.set) self.scrollResults.config(command=self.listResults.yview) self.entrySearch.grid(row=0, column=0, columnspan=2, sticky="we", padx=5, pady=5) self.frameResults.grid(row=1, column=0, columnspan=3, sticky="nswe", padx=5, pady=5) self.buttonSearch.grid(row=0, column=2, padx=5, pady=5, sticky="e") self.buttonAdd.grid(row=2, column=1, padx=5, pady=5, sticky="e") self.buttonClose.grid(row=2, column=2, padx=5, pady=5, sticky="e") self.gui.protocol("WM_DELETE_WINDOW", self.actionClose) self.buttonClose.bind("<ButtonRelease>", self.actionClose) self.buttonAdd.bind("<ButtonRelease>", self.actionAdd) self.buttonSearch.bind("<ButtonRelease>", self.actionSearch) self.entrySearch.bind("<Return>", self.actionSearch) self.gui.update() self.gui.minsize(self.gui.winfo_width(), self.gui.winfo_height()) self.gui.mainloop() def actionAdd(self, event): try: selection = self.listResults.selection_get() selectionSplit = selection.split(":\t", 1) selectionSplit2 = selectionSplit[1].split("\t") if not (selectionSplit[0], selectionSplit2[0]) in self.parent.optimizer.speciesList: self.parent.optimizer.speciesList.append((selectionSplit[0], selectionSplit2[0].strip())) self.caller.gui.event_generate("<<Update>>") except tkinter.TclError : # no selection pass def actionSearch(self, event): query = self.entrySearch.get() if(query): self.listResults.delete(0, "end") results = self.parent.optimizer.SPSUMHandler.search(query) # sort results by nr of CDS results = sorted(results.items(), reverse=True, key=lambda x: (int(x[1][1]))) for name, (taxid, ncs) in results: self.listResults.insert("end", taxid + ":\t " + name + " \t(" + ncs + " CDS)") def actionClose(self, event=None): self.caller.gui.event_generate("<<Update>>", when="tail") self.gui.destroy()
class CopyToMoveTo: """ Minimalist file manager intended to be used independently or alongside Windows Explorer """ def __init__(self, root): """ Setup window geometry, init settings, define widgets + layout """ self.master = root self.master.title("CopyTo-MoveTo") self.master.iconbitmap(f"{dirname(__file__)}/icon.ico") if system() != "Windows": self.master.withdraw() messagebox.showwarning( "Incompatible platform", "CopyTo-MoveTo currently supports Windows platforms only.") raise SystemExit #Settings: self.settings_show_hidden = BooleanVar() self.settings_include_files = BooleanVar(value=True) self.settings_ask_overwrite = BooleanVar() self.settings_ask_overwrite.trace("w", self.settings_exclusives) self.settings_rename_dupes = BooleanVar(value=True) self.settings_rename_dupes.trace("w", self.settings_exclusives) self.settings_multiselect = BooleanVar(value=True) self.settings_select_dirs = BooleanVar(value=True) self.settings_select_dirs.trace("w", self.settings_mutuals) self.settings_select_files = BooleanVar(value=True) self.settings_select_files.trace("w", self.settings_mutuals) self.settings_geometry = None self.appdata_dir = getenv("APPDATA") + "/CopyTo-MoveTo" self.appdata_path = self.appdata_dir + "/settings.json" self.settings = self.init_settings() if self.settings: self.settings_geometry = self.settings["geometry"] self.settings_show_hidden.set(self.settings["show_hidden"]) self.settings_include_files.set(self.settings["include_files"]) self.settings_ask_overwrite.set(self.settings["ask_overwrite"]) self.settings_rename_dupes.set(self.settings["rename_dupes"]) self.settings_multiselect.set(self.settings["multiselect"]) self.settings_select_dirs.set(self.settings["select_dirs"]) self.settings_select_files.set(self.settings["select_files"]) self.dialog_showing = BooleanVar() self.help_showing = BooleanVar() self.about_showing = BooleanVar() self.master.protocol("WM_DELETE_WINDOW", self.master_close) self.master.bind("<Control-w>", self.master_close) #Geometry: self.master.minsize(width=450, height=200) if self.settings_geometry: self.master.geometry(self.settings_geometry) self.master.update() else: self.master.geometry("600x400") self.master.update_idletasks() (width_offset, height_offset) = Ufd.get_offset(self.master) self.master.geometry(f"+{width_offset}+{height_offset}") self.master.update_idletasks() # Menu: self.main_menu = Menu(self.master) self.master.config(menu=self.main_menu) self.file_menu = Menu(self.main_menu, tearoff=0) self.settings_menu = Menu(self.main_menu, tearoff=0) self.main_menu.add_cascade(label="File", menu=self.file_menu) self.main_menu.add_cascade(label="Settings", menu=self.settings_menu) self.file_menu.add_command(label="Open Source(s)", accelerator="Ctrl+O", command=lambda: self.show_ufd(source=True)) self.master.bind("<Control-o>", lambda event: self.show_ufd(source=True)) self.file_menu.add_command(label="Open Destination(s)", accelerator="Ctrl+K+O", command=lambda: self.show_ufd(source=False)) self.master.bind("<Control-k>o", lambda event: self.show_ufd(source=False)) self.file_menu.add_separator() self.file_menu.add_command(label="Help / Commands", command=self.show_help) self.file_menu.add_command(label="About", command=self.show_about) #Settings menu: self.settings_menu.add_checkbutton(label="Show Hidden Files & Folders", variable=self.settings_show_hidden, onvalue=True, offvalue=False) self.settings_menu.add_checkbutton( label="Include Files in Tree", variable=self.settings_include_files, onvalue=True, offvalue=False) self.settings_menu.add_separator() self.settings_menu.add_checkbutton( label="Ask Overwrite", variable=self.settings_ask_overwrite, onvalue=True, offvalue=False) self.settings_menu.add_checkbutton(label="Rename Duplicates", variable=self.settings_rename_dupes, onvalue=True, offvalue=False) self.settings_menu.add_separator() self.settings_menu.add_checkbutton(label="Multiselect", variable=self.settings_multiselect, onvalue=True, offvalue=False) self.settings_menu.add_checkbutton(label="Select Folders", variable=self.settings_select_dirs, onvalue=True, offvalue=False) self.settings_menu.add_checkbutton(label="Select Files", variable=self.settings_select_files, onvalue=True, offvalue=False) self.main_menu.add_separator() #Menu commands: self.main_menu.add_command(label="Swap Selected", command=self.swap_selected) self.master.bind("<Control-s>", lambda event: self.swap_selected()) self.main_menu.add_command(label="Clear Selected", command=self.clear_selected) self.master.bind("<Control-x>", lambda event: self.clear_selected()) self.main_menu.add_command(label="Clear All", command=self.clear_all) self.master.bind("<Control-Shift-X>", lambda event: self.clear_all()) self.main_menu.add_separator() self.main_menu.add_command(label="COPY", command=lambda: self._submit(copy=True)) self.master.bind("<Control-Shift-Return>", lambda event: self._submit(copy=True)) self.main_menu.add_command(label="MOVE", command=lambda: self._submit(copy=False)) self.master.bind("<Control-Return>", lambda event: self._submit(copy=False)) # Body: self.paneview = PanedWindow(self.master, sashwidth=7, bg="#cccccc", bd=0, orient="vertical") self.top_pane = PanedWindow(self.paneview) self.bottom_pane = PanedWindow(self.paneview) self.paneview.add(self.top_pane) self.paneview.add(self.bottom_pane) self.label_source = Label(self.top_pane, text="Source(s):") self.label_dest = Label(self.bottom_pane, text="Destination(s):") self.y_scrollbar_source = Scrollbar(self.top_pane, orient="vertical") self.x_scrollbar_source = Scrollbar(self.top_pane, orient="horizontal") self.y_scrollbar_dest = Scrollbar(self.bottom_pane, orient="vertical") self.x_scrollbar_dest = Scrollbar(self.bottom_pane, orient="horizontal") self.list_box_source = Listbox( self.top_pane, selectmode="extended", yscrollcommand=self.y_scrollbar_source.set, xscrollcommand=self.x_scrollbar_source.set) self.list_box_dest = Listbox(self.bottom_pane, selectmode="extended", yscrollcommand=self.y_scrollbar_dest.set, xscrollcommand=self.x_scrollbar_dest.set) self.x_scrollbar_source.config(command=self.list_box_source.xview) self.y_scrollbar_source.config(command=self.list_box_source.yview) self.x_scrollbar_dest.config(command=self.list_box_dest.xview) self.y_scrollbar_dest.config(command=self.list_box_dest.yview) # Layout: self.master.rowconfigure(0, weight=1) self.master.columnconfigure(0, weight=1) self.top_pane.rowconfigure(1, weight=1) self.top_pane.columnconfigure(0, weight=1) self.bottom_pane.rowconfigure(1, weight=1) self.bottom_pane.columnconfigure(0, weight=1) self.paneview.paneconfigure(self.top_pane, minsize=100) self.paneview.paneconfigure(self.bottom_pane, minsize=100) self.paneview.grid(row=0, column=0, sticky="nsew") self.label_source.grid(row=0, column=0, sticky="w") self.list_box_source.grid(row=1, column=0, sticky="nsew") self.y_scrollbar_source.grid(row=1, column=1, sticky="ns") self.x_scrollbar_source.grid(row=2, column=0, sticky="ew") self.label_dest.grid(row=0, column=0, sticky="w", columnspan=2) self.list_box_dest.grid(row=1, column=0, sticky="nsew") self.y_scrollbar_dest.grid(row=1, column=1, sticky="ns") self.x_scrollbar_dest.grid(row=2, column=0, sticky="ew") def __str__(self): """Return own address""" return f"CopyTo-MoveTo @ {hex(id(self))}" def init_settings(self): """Called on startup, loads, parses, and returns json settings.""" if exists(self.appdata_path): with open(self.appdata_path, "r") as settings_file: settings_json = settings_file.read() settings = loads(settings_json) return settings else: return None def settings_exclusives(self, *args): """ Callback assigned to settings that are mutually exclusive, to prevent logical/runtime errors or unexpected behavior. """ if args[0] == "PY_VAR2": if self.settings_ask_overwrite.get() == 1: self.settings_rename_dupes.set(0) return elif args[0] == "PY_VAR3": if self.settings_rename_dupes.get() == 1: self.settings_ask_overwrite.set(0) return def settings_mutuals(self, *args): """ Prevent select folders & select files from being disabled concurrently If both are unselected, reselect the one we didn't just deselect on. """ if self.settings_select_dirs.get() == 0 \ and self.settings_select_files.get() == 0: if args[0] == "PY_VAR5": self.settings_select_files.set(1) elif args[0] == "PY_VAR6": self.settings_select_dirs.set(1) def master_close(self, event=None): """ Similar to utils.toplevel_close(). writes settings to the disk as json. """ settings = { "geometry": self.master.geometry(), "show_hidden": self.settings_show_hidden.get(), "include_files": self.settings_include_files.get(), "ask_overwrite": self.settings_ask_overwrite.get(), "rename_dupes": self.settings_rename_dupes.get(), "multiselect": self.settings_multiselect.get(), "select_dirs": self.settings_select_dirs.get(), "select_files": self.settings_select_files.get(), } settings_json = dumps(settings) if not exists(self.appdata_dir): mkdir(self.appdata_dir) with open(self.appdata_path, "w+") as settings_file: settings_file.write(settings_json) if self.dialog_showing.get() == 1: self.ufd.cancel() self.master.destroy() def toplevel_close(self, dialog, boolean): """ This callback flips the value for a given toplevel_showing boolean to false, before disposing of the toplevel. """ boolean.set(0) dialog.destroy() def swap_selected(self): """Swap list entries between source & destination""" source_selection = list(self.list_box_source.curselection()) dest_selection = list(self.list_box_dest.curselection()) for i in reversed(source_selection): item = self.list_box_source.get(i) self.list_box_source.delete(i) self.list_box_dest.insert("0", item) for i in reversed(dest_selection): item = self.list_box_dest.get(i) self.list_box_dest.delete(i) self.list_box_source.insert("0", item) def clear_selected(self): """Removes selected (highlighted) item(s) from a given listbox""" source_selection = list(self.list_box_source.curselection()) dest_selection = list(self.list_box_dest.curselection()) if source_selection: for i in reversed(source_selection): self.list_box_source.delete(i) self.list_box_source.selection_set(source_selection[0]) if dest_selection: for i in reversed(dest_selection): self.list_box_dest.delete(i) self.list_box_dest.selection_set(dest_selection[0]) def clear_all(self): """Clears both listboxes in the main UI, resetting the form.""" self.list_box_source.delete(0, "end") self.list_box_dest.delete(0, "end") def handled(fn): """Filesystem operations are wrapped here for error handling""" @wraps(fn) def inner(self, *args, **kwargs): try: fn(self, *args, **kwargs) return True except (PermissionError, FileNotFoundError) as err: self.skipped_err.append(f"{err.args[1]}:\n" + (" => ".join(args))) return False return inner @handled def _copy(self, path, destination): """Wrapper for shutil.copy2() || shutil.copytree()""" if isfile(path): copy2(path, destination) else: copytree(path, destination) @handled def _move(self, path, destination): """Wrapper for shutil.move()""" move(path, destination) @handled def _delete(self, path): """Wrapper for os.remove() || shutil.rmtree()""" if isfile(path): remove(path) elif isdir(path): rmtree(path) def disabled_ui(fn): """Menubar is disabled during operations""" @wraps(fn) def inner(self, *args, **kwargs): self.main_menu.entryconfig("File", state="disabled") self.main_menu.entryconfig("Settings", state="disabled") self.main_menu.entryconfig("Clear Selected", state="disabled") self.main_menu.entryconfig("Clear All", state="disabled") self.main_menu.entryconfig("COPY", state="disabled") self.main_menu.entryconfig("MOVE", state="disabled") fn(self, *args, **kwargs) self.main_menu.entryconfig("File", state="normal") self.main_menu.entryconfig("Settings", state="normal") self.main_menu.entryconfig("Clear Selected", state="normal") self.main_menu.entryconfig("Clear All", state="normal") self.main_menu.entryconfig("COPY", state="normal") self.main_menu.entryconfig("MOVE", state="normal") return inner def _submit(self, copy): """Thread/wrapper for submit() so we don't block the UI during operations""" self.thread = Thread(target=self.submit, args=(copy, ), daemon=True) self.thread.start() @disabled_ui def submit(self, copy): """ Move or copy each item in the origin list to the path in the destination list. Supports no more than one destination directory where copy == False. Ask Overwrite and Rename Dupes will alter the way we handle existing data standing in the way. By default, duplicates are renamed with an index. A messagebox can complain to the user if shutil raises a PermissionError, and the operation is skipped. """ if (self.list_box_dest.size() > 1) and not copy: messagebox.showwarning( "Invalid Operation", "Move operation only supports a single destination directory.") return sources = self.list_box_source.get(0, "end") destinations = self.list_box_dest.get(0, "end") self.skipped_err = [] for j, destination in enumerate(destinations): if isfile(destination): self.skipped_err.append(f"Invalid destination: {destination}") continue for i, source in enumerate(sources): self.progress(i, j) (_, filename) = split(source) future_destination = join(destination + sep, filename) if exists(future_destination): if not self.settings_ask_overwrite.get() \ and not self.settings_rename_dupes.get(): if not self._delete(future_destination): continue if self.settings_ask_overwrite.get(): if self.ask_overwrite(future_destination): if not self._delete(future_destination): continue else: continue if self.settings_rename_dupes.get(): future_destination = self.name_dupe(future_destination) if copy: if not self._copy(source, future_destination): continue else: if not self._move(source, future_destination): continue self.list_box_source.delete(0, "end") self.list_box_dest.delete(0, "end") if self.skipped_err: messagebox.showerror(title="Error(s)", message="\n\n".join(self.skipped_err)) @staticmethod def name_dupe(path): """ Renames the file or directory until it doesn't exist in the destination with that name anymore, by appending the filename with an index wrapped in parenthesis. (Windows platforms) file.txt => file (1).txt => file (2).txt """ if system() != "Windows": raise OSError("For use with Windows filesystems.") path_ = path (root, filename) = split(path_) if isdir(path_): title = filename ext = None else: (title, ext) = splitext(filename) filecount = 0 while exists(path_): filecount += 1 new_title = title + " (" + str(filecount) + ")" if ext: new_title = new_title + ext path_ = join(root, new_title) return path_ def ask_overwrite(self, future_destination): """Messagebox result returned as truth value""" return messagebox.askyesno( title="Path Conflict", message=f"Overwrite:\n\n{future_destination}?\n\n" \ f"YES - Overwrite\nNO - Skip" ) def progress(self, i, j): """ Visualize operands in GUI during operations i = current source operand index j = current destination operand index """ for y, _ in enumerate(self.list_box_source.get(0, "end")): if y != i: self.list_box_source.itemconfigure(y, bg="#FFFFFF", fg="#000000") else: self.list_box_source.itemconfigure(y, bg="#cccccc", fg="#000000") for x, _ in enumerate(self.list_box_dest.get(0, "end")): if x != j: self.list_box_dest.itemconfigure(x, bg="#FFFFFF", fg="#000000") else: self.list_box_dest.itemconfigure(x, bg="#cccccc", fg="#000000") self.master.update() #Toplevels: def show_about(self): """ Displays a static dialog that doesn't allow additional instances of itself to be created while showing. """ if self.about_showing.get() == 0: self.about_showing.set(1) try: with open(f"{dirname(__file__)}/about.txt", "r") as aboutfile: about_info = aboutfile.read() except FileNotFoundError: messagebox.showerror("Error", "File not found") self.about_showing.set(0) return else: self.about = Toplevel() self.about.title("About") self.about.iconbitmap(f"{dirname(__file__)}/icon.ico") self.about.geometry("600x400") self.about.resizable(0, 0) self.about.update_idletasks() (width_offset, height_offset) = Ufd.get_offset(self.about) self.about.geometry(f"+{width_offset-75}+{height_offset-75}") self.about.update_idletasks() self.about_message = Label( self.about, text=about_info, justify="left", wraplength=(self.about.winfo_width() - 25)) self.about_message.grid(sticky="nsew") self.about.protocol( "WM_DELETE_WINDOW", lambda: self.toplevel_close( self.about, self.about_showing)) def show_help(self): """ Displays a scrollable dialog that doesn't allow additional instances of itself to be created while showing. """ if self.help_showing.get() == 0: self.help_showing.set(1) try: with open(f"{dirname(__file__)}/help.txt", "r") as helpfile: help_info = helpfile.read() except FileNotFoundError: messagebox.showerror("Error", "File not found") self.help_showing.set(0) return else: self.help_window = Toplevel() self.help_window.title("Help") self.help_window.iconbitmap(f"{dirname(__file__)}/icon.ico") self.help_window.geometry("500x300") self.help_window.update_idletasks() (width_offset, height_offset) = Ufd.get_offset(self.help_window) self.help_window.geometry( f"+{width_offset+75}+{height_offset-75}") self.help_window.update_idletasks() self.message_y_scrollbar = Scrollbar(self.help_window, orient="vertical") self.help_text = Text( self.help_window, wrap="word", yscrollcommand=self.message_y_scrollbar.set) self.help_window.rowconfigure(0, weight=1) self.help_window.columnconfigure(0, weight=1) self.help_text.grid(row=0, column=0, sticky="nsew") self.message_y_scrollbar.grid(row=0, column=1, sticky="nse") self.message_y_scrollbar.config(command=self.help_text.yview) self.help_text.insert("end", help_info) self.help_text.config(state="disabled") self.help_window.protocol( "WM_DELETE_WINDOW", lambda: self.toplevel_close( self.help_window, self.help_showing)) def show_ufd(self, source=True): """ Display Ufd w/ appropriate kwargs => Populate GUI w/ result""" if self.dialog_showing.get() == 0: self.dialog_showing.set(1) self.ufd = Ufd(title="Add Items", show_hidden=self.settings_show_hidden.get(), include_files=self.settings_include_files.get(), multiselect=self.settings_multiselect.get(), select_dirs=self.settings_select_dirs.get(), select_files=self.settings_select_files.get(), unix_delimiter=False, stdout=False) for result in self.ufd(): if source: self.list_box_source.insert("end", result) else: self.list_box_dest.insert("end", result) self.dialog_showing.set(0)
class ConnectionDialog: """ Class handling the user input for the connection with the controller .. attribute:: host The IP of the host, - given by the user input, - which we want to connect to. .. attribute:: port The port, - given by the user input, - on which we reach the host. .. attribute:: password The users password .. warning:: Validation | None of the above entries are validated, hence if the user mistypes, | or misunderstands the entry field, it is possible that a non-legit IP address, | or port is returned. That can lead to exceptions, therefore checking these values, | before is advised. """ def __init__(self, parent): self.top = Toplevel(parent) self.top.columnconfigure(0, weight=MainWindow.WEIGHT) self.top.columnconfigure(1, weight=MainWindow.WEIGHT) for i in range(4): self.top.rowconfigure(i, weight=MainWindow.WEIGHT) host_label = Label(self.top, text='Host: ', background=MainWindow.BACKGROUND_COLOR) host_label.grid(row=0, column=0, sticky=MainWindow.FILL) self.host_entry = Entry(self.top, background=MainWindow.BACKGROUND_COLOR) self.host_entry.grid(row=0, column=1, sticky=MainWindow.FILL) port_label = Label(self.top, text='Port: ', background=MainWindow.BACKGROUND_COLOR) port_label.grid(row=1, column=0, sticky=MainWindow.FILL) self.port_entry = Entry(self.top, background=MainWindow.BACKGROUND_COLOR) self.port_entry.grid(row=1, column=1, sticky=MainWindow.FILL) password_label = Label(self.top, text='Password: '******'*', background=MainWindow.BACKGROUND_COLOR) self.password_entry.grid(row=2, column=1, sticky=MainWindow.FILL) button_frame = Frame(self.top) button_frame.grid(row=3, column=0, sticky=MainWindow.FILL, columnspan=2) connect_button = Button(button_frame, text='Connect.', command=self.__connect, background=MainWindow.BACKGROUND_COLOR) connect_button.pack(fill=BOTH) def __connect(self) -> None: self.host = self.host_entry.get() self.port = self.port_entry.get() self.password = self.password_entry.get() self.top.destroy()
class SpeciesSearchDialog: def __init__(self, parent, caller): # main window self.parent = parent # dialog that called this second dialog self.caller = caller self.gui = Toplevel(parent.guiRoot) self.gui.grab_set() self.gui.focus() self.gui.columnconfigure(0, weight=1) self.gui.rowconfigure(1, weight=1) self.entrySearch = Entry(self.gui) self.buttonSearch = Button(self.gui, text=" Search ") self.buttonAdd = Button(self.gui, text=" Add Species ") self.buttonClose = Button(self.gui, text=" Close Window ") self.frameResults = Frame(self.gui) self.frameResults.columnconfigure(0, weight=1) self.frameResults.rowconfigure(0, weight=1) self.scrollResults = Scrollbar(self.frameResults, orient="vertical") self.scrollResults.grid(row=0, column=1, sticky="ns") self.listResults = Listbox(self.frameResults, width=70, height=20) self.listResults.grid(row=0, column=0, sticky="nswe") self.listResults.config(yscrollcommand=self.scrollResults.set) self.scrollResults.config(command=self.listResults.yview) self.entrySearch.grid(row=0, column=0, columnspan=2, sticky="we", padx=5, pady=5) self.frameResults.grid(row=1, column=0, columnspan=3, sticky="nswe", padx=5, pady=5) self.buttonSearch.grid(row=0, column=2, padx=5, pady=5, sticky="e") self.buttonAdd.grid(row=2, column=1, padx=5, pady=5, sticky="e") self.buttonClose.grid(row=2, column=2, padx=5, pady=5, sticky="e") self.gui.protocol("WM_DELETE_WINDOW", self.actionClose) self.buttonClose.bind("<ButtonRelease>", self.actionClose) self.buttonAdd.bind("<ButtonRelease>", self.actionAdd) self.buttonSearch.bind("<ButtonRelease>", self.actionSearch) self.entrySearch.bind("<Return>", self.actionSearch) self.gui.update() self.gui.minsize(self.gui.winfo_width(), self.gui.winfo_height()) self.gui.mainloop() def actionAdd(self, event): try: selection = self.listResults.selection_get() selectionSplit = selection.split(":\t", 1) selectionSplit2 = selectionSplit[1].split("\t") if not (selectionSplit[0], selectionSplit2[0]) in self.parent.optimizer.speciesList: self.parent.optimizer.speciesList.append((selectionSplit[0], selectionSplit2[0].strip())) self.caller.gui.event_generate("<<Update>>") except tkinter.TclError: # no selection pass def actionSearch(self, event): query = self.entrySearch.get() if query: self.listResults.delete(0, "end") results = self.parent.optimizer.SPSUMHandler.search(query) # sort results by nr of CDS results = sorted(results.items(), reverse=True, key=lambda x: (int(x[1][1]))) for name, (taxid, ncs) in results: self.listResults.insert("end", taxid + ":\t " + name + " \t(" + ncs + " CDS)") def actionClose(self, event=None): self.caller.gui.event_generate("<<Update>>", when="tail") self.gui.destroy()
class ScmGui: """Tkinter based GUI (for Windows).""" # pylint: disable=too-many-instance-attributes # pylint: disable=too-many-public-methods def __init__(self, master): """Initialise.""" # pylint: disable=too-many-statements # super().__init__(None) self.master = master self.issue_window = None self.issue_text = None self.report_window = None self.report_text = None self.issues = None self.scm = None self.gotdata = False self.thread = False self.grouping = None self.reports = None self.menus = [] self.menu_fixit = None self.notify_text = None master.title("SCM Helper") self.create_main_window() self.create_menu() set_notify(self.notify_text) self.issues = IssueHandler() self.scm = API(self.issues) if self.scm.get_config_file() is False: msg = "Error in config file - see status window for details." messagebox.showerror("Error", msg, parent=self.master) cfgmsg = "" else: cfgmsg = check_default(self.scm) self.api_init = False msg = "Welcome to SCM Helper by Colin Robbins.\n" msg += cfgmsg msg += "Please enter your password.\n" self.notify_text.insert(END, msg) self.notify_text.config(state=DISABLED) def create_main_window(self): """Create the main window.""" top_frame = Frame(self.master) top_frame.grid(row=0, column=0, sticky=W + E) label = Label(top_frame, text="Password: "******"") password = Entry(top_frame, show="*", textvariable=self.__password, width=20) password.grid(row=0, column=1, pady=10, padx=10) msg = "Analyse" self.button_analyse = Button(top_frame, text=msg, command=self.analyse_window) self.button_analyse.grid(row=0, column=2, pady=10, padx=10) self.master.bind("<Return>", self.analyse_enter) self.button_backup = Button(top_frame, text="Backup", command=self.backup) self.button_backup.grid(row=0, column=3, pady=10, padx=10) self.button_fixit = Button(top_frame, text="Fixit", command=self.fixit) self.button_fixit.config(state=DISABLED) self.button_fixit.grid(row=0, column=4, pady=10, padx=10) top_group = LabelFrame(self.master, text="Notifications...", pady=5, padx=5) top_group.grid(row=1, column=0, columnspan=5, pady=10, padx=10, sticky=NSEW) self.master.columnconfigure(0, weight=1) self.master.rowconfigure(1, weight=1) top_group.columnconfigure(0, weight=1) top_group.rowconfigure(0, weight=1) self.notify_text = scrolledtext.ScrolledText(top_group, width=60, height=20) self.notify_text.grid(row=0, column=0, sticky=NSEW) def create_menu(self): """Create Menus.""" # pylint: disable=too-many-statements menubar = Menu(self.master) file = Menu(menubar, tearoff=0) file.add_command(label="Open Archive", command=self.open_archive) self.menus.append([file, "Open Archive"]) file.add_separator() file.add_command(label="Exit", command=self.master.quit) menubar.add_cascade(label="File", menu=file) cmd = Menu(menubar, tearoff=0) cmd.add_command(label="Edit Config", command=self.edit_config) self.menus.append([cmd, "Edit Config"]) cmd.add_separator() cmd.add_command(label="Create / Update Lists", command=self.create_lists, state=DISABLED) self.menus.append([cmd, "Create / Update Lists"]) cmd.add_command(label="Fix Errors", command=self.fixit, state=DISABLED) self.menu_fixit = [cmd, "Fix Errors"] label = "Fix Search index" cmd.add_command(label=label, command=self.fix_search, state=DISABLED) self.menus.append([cmd, label]) label = "Update SE Categories" cmd.add_command(label=label, command=self.fix_secat, state=DISABLED) self.menus.append([cmd, label]) menubar.add_cascade(label="Edit", menu=cmd) cmd = Menu(menubar, tearoff=0) cmd.add_command(label="Analyse Facebook", command=self.facebook, state=DISABLED) self.menus.append([cmd, "Analyse Facebook"]) label = "Analyse Swim England File" cmd.add_command(label=label, command=self.swim_england, state=DISABLED) self.menus.append([cmd, label]) label = "Analyse Swim England Registrations Online" cmd.add_command(label=label, command=self.swim_england_online, state=DISABLED) self.menus.append([cmd, label]) cmd.add_command(label="List Coaches", command=self.coaches, state=DISABLED) self.menus.append([cmd, "List Coaches"]) label = "Show Swimmers Covid Declaration per session" cmd.add_command(label=label, command=self.covid, state=DISABLED) self.menus.append([cmd, label]) label = "List Swimmers sessions" cmd.add_command(label=label, command=self.sessions, state=DISABLED) self.menus.append([cmd, label]) label = "Show Not-confirmed Emails" cmd.add_command(label=label, command=self.confirm, state=DISABLED) self.menus.append([cmd, label]) menubar.add_cascade(label="Reports", menu=cmd) record = Menu(menubar, tearoff=0) record.add_command(label="Process Records", command=self.process_records) label = "Read New Swim Times" record.add_command(label=label, command=self.new_times, state=DISABLED) self.menus.append([record, label]) menubar.add_cascade(label="Records", menu=record) about = Menu(menubar, tearoff=0) about.add_command(label="About...", command=xabout) about.add_command(label="Help", command=xhelp) about.add_command(label="License", command=xlicense) menubar.add_cascade(label="About", menu=about) self.master.config(menu=menubar) def scm_init(self): """Initialise SCM.""" self.notify_text.config(state=NORMAL) password = self.__password.get() self.clear_data() self.api_init = False if password: if self.scm.initialise(password) is False: messagebox.showerror( "Error", "Cannot initialise SCM (wrong password?)") self.clear_data() self.notify_text.config(state=DISABLED) return False self.api_init = True return True messagebox.showerror("Password", "Please give a password!") self.notify_text.config(state=DISABLED) return False def prep_report(self, create=True, delete=True): """Prepare for a report.""" if self.gotdata is False: messagebox.showerror("Error", "Run analyse first to collect data") return False if create and (self.report_window is None): self.create_report_window() if self.report_window: self.report_text.config(state=NORMAL) self.report_text.delete("1.0", END) self.notify_text.config(state=NORMAL) if delete: self.notify_text.delete("1.0", END) return True def open_archive(self): """Open archive file.""" if self.thread: return # already running if self.scm_init() is False: return self.thread = True AnalysisThread(self, True).start() def swim_england(self): """Process Swim England File.""" if self.prep_report() is False: return csv = Csv() home = str(Path.home()) cfg = os.path.join(home, CONFIG_DIR) dir_opt = {} dir_opt["title"] = "Find Swim England File" dir_opt["initialdir"] = cfg dir_opt["parent"] = self.report_window dir_opt["defaultextension"] = ".csv" where = filedialog.askopenfilename(**dir_opt) if csv.readfile(where, self.scm) is False: messagebox.showerror("Error", "Could not read CSV file") self.notify_text.config(state=DISABLED) self.report_text.config(state=DISABLED) return if wrap(10, csv.analyse, self.scm) is False: self.notify_text.config(state=DISABLED) self.report_text.config(state=DISABLED) return output = wrap(None, csv.print_errors) del csv self.report_text.insert(END, output) self.report_text.config(state=DISABLED) self.notify_text.config(state=DISABLED) self.report_window.lift() def swim_england_online(self): """Window for reports.""" if self.thread: return # already running if self.prep_report(False) is False: return self.thread = True SwimEnglandThread(self).start() def facebook(self): """Window for reports.""" if self.thread: return # already running if self.prep_report(False) is False: return self.thread = True FacebookThread(self).start() def confirm(self): """Confirm email Report.""" if self.prep_report() is False: return output = self.issues.confirm_email() self.report_text.insert(END, output) self.report_text.config(state=DISABLED) self.notify_text.config(state=DISABLED) self.report_window.lift() def coaches(self): """Coaches Report.""" if self.prep_report() is False: return output = wrap(None, self.scm.sessions.print_coaches) self.report_text.insert(END, output) self.report_text.config(state=DISABLED) self.notify_text.config(state=DISABLED) self.report_window.lift() def covid(self): """Covid Report.""" if self.prep_report() is False: return output = wrap(None, self.scm.sessions.print_swimmers_covid) self.report_text.insert(END, output) self.report_text.config(state=DISABLED) self.notify_text.config(state=DISABLED) self.report_window.lift() def sessions(self): """Swimmers per Sessions Report.""" if self.prep_report() is False: return output = wrap(None, self.scm.members.print_swimmers_sessions) self.report_text.insert(END, output) self.report_text.config(state=DISABLED) self.notify_text.config(state=DISABLED) self.report_window.lift() def edit_config(self): """Edit Config.""" home = str(Path.home()) cfg = os.path.join(home, CONFIG_DIR, CONFIG_FILE) Edit(self.master, cfg, self.scm, self) def create_lists(self): """Create Lists.""" if self.gotdata is False: messagebox.showerror("Error", "Run analyse first to collect data") return if self.thread: return # already running self.thread = True UpdateThread(self).start() def analyse_window(self): """Window for analysis result.""" if self.thread: return # already running if self.scm_init() is False: return self.thread = True AnalysisThread(self, False).start() def analyse_enter(self, event): """Window for analysis result.""" debug(f"Event: {event}", 7) self.analyse_window() def fix_search(self): """Window for reports.""" if self.thread: return # already running if self.gotdata is False: messagebox.showerror("Error", "Analyse data first, before fixing (2)") return self.thread = True SearchThread(self).start() def fix_secat(self): """Window for reports.""" if self.thread: return # already running if self.gotdata is False: messagebox.showerror("Error", "Analyse data first, before fixing (3)") return self.thread = True SecatThread(self).start() def fixit(self): """Window for reports.""" if self.thread: return # already running if self.gotdata is False: messagebox.showerror("Error", "Analyse data first, before fixing") return self.set_buttons(DISABLED) length = len(self.scm.fixable) if length == 0: messagebox.showerror("Error", "Nothing to fix") self.set_buttons(NORMAL) return wrap(None, self.scm.apply_fixes) self.set_buttons(NORMAL) def backup(self): """Window for reports.""" if self.thread: return # already running if self.scm_init() is False: return self.thread = True BackupThread(self).start() def clear_data(self): """Prepare to rerun.""" wrap(None, self.scm.delete) self.gotdata = False def create_report_window(self): """Create the reports window.""" self.report_window = Toplevel(self.master) self.report_window.title("SCM Helper - Report Window") top_frame = Frame(self.report_window) top_frame.grid(row=0, column=0, sticky=W + E) txt = "Report..." top_group = LabelFrame(self.report_window, text=txt, pady=5, padx=5) top_group.grid(row=0, column=0, pady=10, padx=10, sticky=NSEW) self.report_window.columnconfigure(0, weight=1) self.report_window.rowconfigure(0, weight=1) top_group.columnconfigure(0, weight=1) top_group.rowconfigure(0, weight=1) self.report_text = scrolledtext.ScrolledText(top_group, width=80, height=40) self.report_text.grid(row=0, column=0, sticky=NSEW) self.report_window.protocol("WM_DELETE_WINDOW", self.close_report_window) def close_report_window(self): """Close report window.""" self.report_window.destroy() self.report_window = None def create_issue_window(self): """Create the results window.""" self.issue_window = Toplevel(self.master) self.issue_window.title("SCM Helper - Issue Window") self.reports = StringVar() self.reports.set("All Reports") top_frame = Frame(self.issue_window) top_frame.grid(row=0, column=0, sticky=W + E) label = Label(top_frame, text="Select Report: ") label.grid(row=0, column=0, pady=10, padx=10) rpts = [resp.title() for resp in REPORTS] all_reports = ["All Reports"] + rpts menu = OptionMenu( top_frame, self.reports, *all_reports, command=self.process_issue_option, ) menu.grid(row=0, column=1, pady=10, padx=10) self.grouping = StringVar() self.grouping.set("Error") label = Label(top_frame, text="Group Report by: ") label.grid(row=0, column=2, pady=10, padx=10) menu = OptionMenu( top_frame, self.grouping, "Error", "Member", command=self.process_issue_option, ) menu.grid(row=0, column=3, pady=10, padx=10) txt = "Analysis..." top_group = LabelFrame(self.issue_window, text=txt, pady=5, padx=5) top_group.grid(row=1, column=0, columnspan=4, pady=10, padx=10, sticky=NSEW) self.issue_window.columnconfigure(0, weight=1) self.issue_window.rowconfigure(1, weight=1) top_group.columnconfigure(0, weight=1) top_group.rowconfigure(0, weight=1) self.issue_text = scrolledtext.ScrolledText(top_group, width=100, height=40) self.issue_text.grid(row=0, column=0, sticky=NSEW) self.issue_window.protocol("WM_DELETE_WINDOW", self.close_issue_window) def close_issue_window(self): """Close issue window.""" self.issue_window.destroy() self.issue_window = None def process_issue_option(self, _): """Process an option selection.""" report = self.reports.get() mode = self.grouping.get() self.issue_text.config(state=NORMAL) self.notify_text.config(state=NORMAL) self.issue_text.delete("1.0", END) if report == "All Reports": report = None else: report = report.lower() if mode == "Error": output = self.issues.print_by_error(report) else: output = self.issues.print_by_name(report) self.issue_text.insert(END, output) self.master.update_idletasks() self.master.after(AFTER, self.set_normal) def set_buttons(self, status): """Change button state.""" self.button_analyse.config(state=status) self.button_backup.config(state=status) for menu, item in self.menus: menu.entryconfig(item, state=status) menu, item = self.menu_fixit if status == NORMAL: self.notify_text.config(state=DISABLED) length = len(self.scm.fixable) if length == 0: self.button_fixit.config(state=DISABLED) menu.entryconfig(item, state=DISABLED) return if self.issue_window: self.issue_text.config(state=DISABLED) else: self.notify_text.config(state=NORMAL) self.button_fixit.config(state=status) menu.entryconfig(item, state=status) def set_normal(self): """Set GUI to normal state after processing.""" self.set_buttons(NORMAL) def new_times(self): """Add new time and process.""" self.process_records(True) def process_records(self, newtimes=False): """Process Records.""" if self.thread: return # already running self.thread = True RecordThread(self, newtimes).start()
class BatchWindow: def __init__(self, grandmother): self.mother = grandmother #in a sense logical, but still weird self.batch_window = Toplevel() self.batch_window.wm_title("Batch Settings Panel") self.batch_window.minsize(width=850, height=955) self.batch_window.maxsize(width=850, height=955) self.scrolled_frame = VerticalScrollGrid(self.batch_window) self.scrolled_frame.grid(row=0, column=0, sticky='EW') self.batch_window.columnconfigure(0, weight=1) self.batch_window.rowconfigure(0, weight=1) # to be used to write batch data values to and from files. Otherwise would not be necessary self.batch_data_values = {} ##-----------------## Label(self.scrolled_frame.frame, text="Parameter").grid(row=0, column=0) Label(self.scrolled_frame.frame, text="Start").grid(row=0, column=1) Label(self.scrolled_frame.frame, text="End").grid(row=0, column=2) Label(self.scrolled_frame.frame, text="Delta Mode").grid(row=0, column=3) Label(self.scrolled_frame.frame, text="Delta").grid(row=0, column=4) Label(self.scrolled_frame.frame, text="Smooth Start").grid(row=0, column=5) Label(self.scrolled_frame.frame, text="Smooth End").grid(row=0, column=6) Label(self.scrolled_frame.frame, text="Cycle Mode").grid(row=0, column=7) Label(self.scrolled_frame.frame, text="Cycle Period").grid(row=0, column=8) ttk.Separator(self.scrolled_frame.frame, orient="horizontal").grid(row=1, columnspan=9, sticky="ew") ##-----------------## class line_item: def __init__(self, parameter_name, which_frame, row_number, start_value, end_value): #Label Label(which_frame, text=parameter_name + ": ").grid(row=row_number, column=0) self.current_value = start_value #Start Value self.start_entry = Entry(which_frame, justify="right", width=8) self.start_entry.insert("end", str(start_value)) self.start_entry.grid(row=row_number, column=1) #End Value self.end_entry = Entry(which_frame, justify="right", width=8) self.end_entry.insert("end", str(end_value)) self.end_entry.grid(row=row_number, column=2) self.end_entry.config(state="disabled") #Delta Checkbox self.delta_check = IntVar() self.delta_check.set(1) self.delta_button = Checkbutton( which_frame, text="Delta Method", variable=self.delta_check, command=self.delta_button_toggle) self.delta_button.grid(row=row_number, column=3) #Delta Value self.delta = Entry(which_frame, justify="right", width=8) self.delta.insert("end", '0') self.delta.grid(row=row_number, column=4) #Smooth Start Checkbox self.smooth_start_check = IntVar() self.smooth_start_check.set(1) self.smooth_start_button = Checkbutton( which_frame, text="Smooth Start", variable=self.smooth_start_check) self.smooth_start_button.grid(row=row_number, column=5) self.smooth_start_button.config(state="disabled") #Smooth End Checkbox self.smooth_end_check = IntVar() self.smooth_end_check.set(1) self.smooth_end_button = Checkbutton( which_frame, text="Smooth End", variable=self.smooth_end_check) self.smooth_end_button.grid(row=row_number, column=6) self.smooth_end_button.config(state="disabled") #Cycle Checkbox self.cycle_check = IntVar() self.cycle_check.set(0) self.cycle_button = Checkbutton( which_frame, text="Cycle", variable=self.cycle_check, command=self.cycle_button_toggle) self.cycle_button.grid(row=row_number, column=7) #Cycle Period self.cycle_period = Entry(which_frame, justify="right", width=8) self.cycle_period.insert("end", '120') self.cycle_period.grid(row=row_number, column=8) self.cycle_period.config(state="disabled") return def delta_button_toggle(self, event=None): checked = self.delta_check.get() if self.cycle_check.get() == self.delta_check.get() == 1: self.cycle_button.invoke() if checked: self.delta.config(state=NORMAL) self.end_entry.config(state="disabled") self.smooth_start_check.set(0) self.smooth_end_check.set(0) self.smooth_start_button.config(state="disabled") self.smooth_end_button.config(state="disabled") else: self.delta.config(state="disabled") self.end_entry.config(state=NORMAL) if self.cycle_check.get() == 0: self.smooth_start_button.config(state=NORMAL) self.smooth_end_button.config(state=NORMAL) def cycle_button_toggle(self, event=None): checked = self.cycle_check.get() if self.cycle_check.get() == self.delta_check.get() == 1: self.delta_button.invoke() if checked: self.cycle_period.config(state=NORMAL) self.end_entry.config(state=NORMAL) self.smooth_start_check.set(0) self.smooth_end_check.set(0) self.smooth_start_button.config(state="disabled") self.smooth_end_button.config(state="disabled") else: self.cycle_period.config(state="disabled") if self.delta_check.get() == 0: self.smooth_start_button.config(state=NORMAL) self.smooth_end_button.config(state=NORMAL) self.end_entry.config(state=NORMAL) ##-----------------## self.batch_data = {} self.batch_data['x_min'] = line_item('x_min', self.scrolled_frame.frame, 2, -2, -1) self.batch_data['x_max'] = line_item('x_max', self.scrolled_frame.frame, 3, 2, -1) self.batch_data['y_min'] = line_item('y_min', self.scrolled_frame.frame, 4, -2, -1) self.batch_data['y_max'] = line_item('y_max', self.scrolled_frame.frame, 5, 2, -1) self.batch_data['iterations'] = line_item('iterations', self.scrolled_frame.frame, 6, 30, 40) self.batch_data['rotation'] = line_item('rotation', self.scrolled_frame.frame, 9, 270, 0) self.batch_data['bailout_value'] = line_item('bailout_value', self.scrolled_frame.frame, 10, 30, 40) self.batch_data['c_real'] = line_item('c_real', self.scrolled_frame.frame, 11, -.5, .7) self.batch_data['c_imag'] = line_item('c_imag', self.scrolled_frame.frame, 12, -.8, .1) self.batch_data['OT_focus1_x'] = line_item('OT_focus1_x', self.scrolled_frame.frame, 13, 30, 40) self.batch_data['OT_focus1_y'] = line_item('OT_focus1_y', self.scrolled_frame.frame, 14, 30, 40) self.batch_data['OT_focus2_x'] = line_item('OT_focus2_x', self.scrolled_frame.frame, 15, 30, 40) self.batch_data['OT_focus2_y'] = line_item('OT_focus2_y', self.scrolled_frame.frame, 16, 30, 40) self.batch_data['OT_focus3_x'] = line_item('OT_focus3_x', self.scrolled_frame.frame, 17, 30, 40) self.batch_data['OT_focus3_y'] = line_item('OT_focus3_y', self.scrolled_frame.frame, 18, 30, 40) self.batch_data['OT_focus4_x'] = line_item('OT_focus4_x', self.scrolled_frame.frame, 19, 30, 40) self.batch_data['OT_focus4_y'] = line_item('OT_focus4_y', self.scrolled_frame.frame, 20, 30, 40) self.batch_data['OT_rotation1'] = line_item('OT_rotation1', self.scrolled_frame.frame, 21, 30, 40) self.batch_data['OT_rotation2'] = line_item('OT_rotation2', self.scrolled_frame.frame, 22, 30, 40) self.batch_data['OT_rotation3'] = line_item('OT_rotation3', self.scrolled_frame.frame, 23, 30, 40) self.batch_data['OT_rotation4'] = line_item('OT_rotation4', self.scrolled_frame.frame, 24, 30, 40) self.batch_data['OT_radius1_1'] = line_item('OT_radius1_1', self.scrolled_frame.frame, 25, 30, 40) self.batch_data['OT_radius1_2'] = line_item('OT_radius1_2', self.scrolled_frame.frame, 26, 30, 40) self.batch_data['OT_radius1_3'] = line_item('OT_radius1_3', self.scrolled_frame.frame, 27, 30, 40) self.batch_data['OT_radius1_4'] = line_item('OT_radius1_4', self.scrolled_frame.frame, 28, 30, 40) self.batch_data['OT_radius2_1'] = line_item('OT_radius2_1', self.scrolled_frame.frame, 29, 30, 40) self.batch_data['OT_radius2_2'] = line_item('OT_radius2_2', self.scrolled_frame.frame, 30, 30, 40) self.batch_data['OT_radius2_3'] = line_item('OT_radius2_3', self.scrolled_frame.frame, 31, 30, 40) self.batch_data['OT_radius2_4'] = line_item('OT_radius2_4', self.scrolled_frame.frame, 32, 30, 40) self.batch_data['OT_trap_count1'] = line_item( 'OT_trap_count1', self.scrolled_frame.frame, 33, 30, 40) self.batch_data['OT_trap_count2'] = line_item( 'OT_trap_count2', self.scrolled_frame.frame, 34, 30, 40) self.batch_data['OT_trap_count3'] = line_item( 'OT_trap_count3', self.scrolled_frame.frame, 35, 30, 40) self.batch_data['OT_trap_count4'] = line_item( 'OT_trap_count4', self.scrolled_frame.frame, 36, 30, 40) self.batch_data['OT_starting_width1'] = line_item( 'OT_starting_width1', self.scrolled_frame.frame, 37, 30, 40) self.batch_data['OT_starting_width2'] = line_item( 'OT_starting_width2', self.scrolled_frame.frame, 38, 30, 40) self.batch_data['OT_starting_width3'] = line_item( 'OT_starting_width3', self.scrolled_frame.frame, 39, 30, 40) self.batch_data['OT_starting_width4'] = line_item( 'OT_starting_width4', self.scrolled_frame.frame, 40, 30, 40) self.batch_data['OT_width_deflection1'] = line_item( 'OT_width_deflection1', self.scrolled_frame.frame, 41, 30, 40) self.batch_data['OT_width_deflection2'] = line_item( 'OT_width_deflection2', self.scrolled_frame.frame, 42, 30, 40) self.batch_data['OT_width_deflection3'] = line_item( 'OT_width_deflection3', self.scrolled_frame.frame, 43, 30, 40) self.batch_data['OT_width_deflection4'] = line_item( 'OT_width_deflection4', self.scrolled_frame.frame, 44, 30, 40) self.batch_data['OT_measure_point1_x'] = line_item( 'OT_measure_point1_x', self.scrolled_frame.frame, 45, 30, 40) self.batch_data['OT_measure_point1_y'] = line_item( 'OT_measure_point1_y', self.scrolled_frame.frame, 46, 30, 40) self.batch_data['OT_measure_point2_x'] = line_item( 'OT_measure_point2_x', self.scrolled_frame.frame, 47, 30, 40) self.batch_data['OT_measure_point2_y'] = line_item( 'OT_measure_point2_y', self.scrolled_frame.frame, 48, 30, 40) self.batch_data['OT_measure_point3_x'] = line_item( 'OT_measure_point3_x', self.scrolled_frame.frame, 49, 30, 40) self.batch_data['OT_measure_point3_y'] = line_item( 'OT_measure_point3_y', self.scrolled_frame.frame, 50, 30, 40) self.batch_data['OT_measure_point4_x'] = line_item( 'OT_measure_point4_x', self.scrolled_frame.frame, 51, 30, 40) self.batch_data['OT_measure_point4_y'] = line_item( 'OT_measure_point4_y', self.scrolled_frame.frame, 52, 30, 40) self.batch_data['OT_loop_distance1'] = line_item( 'OT_loop_distance1', self.scrolled_frame.frame, 53, 5, 5) self.batch_data['OT_loop_distance2'] = line_item( 'OT_loop_distance2', self.scrolled_frame.frame, 54, 5, 5) self.batch_data['OT_loop_distance3'] = line_item( 'OT_loop_distance3', self.scrolled_frame.frame, 55, 5, 5) self.batch_data['OT_loop_distance4'] = line_item( 'OT_loop_distance4', self.scrolled_frame.frame, 56, 5, 5) ##-----------------## bottom_frame = Frame(self.batch_window) bottom_frame.grid(row=5, column=0, sticky="EW") ttk.Separator(bottom_frame, orient="horizontal").grid(row=64, columnspan=3, sticky="ew") Label(bottom_frame, text="Image Numbering Start: ").grid(row=65, column=0) self.image_numbering_entry = Entry(bottom_frame, justify="right", width=8) self.image_numbering_entry.insert("end", '1') self.image_numbering_entry.grid(row=65, column=1) self.batch_data['image_number'] = int(self.image_numbering_entry.get()) Label(bottom_frame, text="Number Of Steps: ").grid(row=66, column=0) self.number_of_steps_entry = Entry(bottom_frame, justify="right", width=8) self.number_of_steps_entry.insert("end", '10') self.number_of_steps_entry.grid(row=66, column=1) self.batch_data['number_of_steps'] = int( self.number_of_steps_entry.get()) self.begin_batch_button = Button(bottom_frame, text="Begin Batch", command=self.batch_thread) self.begin_batch_button.grid(row=66, column=2, sticky="ew") self.get_settings_button = Button( bottom_frame, text="Get Settings From Main Window", command=self.get_settings_from_fractal_object) self.get_settings_button.grid(row=65, column=2) self.save_batch_settings_button = Button( bottom_frame, text="Save Batch Settings", command=lambda: self.save_batch_settings(manual=True)) self.save_batch_settings_button.grid(row=65, column=3, sticky="ew") self.load_batch_settings_button = Button( bottom_frame, text="Load Batch Settings", command=lambda: self.batch_settings_import_from_file( self.mother.fractal_object.settings['save_filename'][1])) self.load_batch_settings_button.grid(row=66, column=3, sticky="ew") return def save_batch_settings(self, manual=False): self.batch_GUI_settings_to_dict() if manual: f = open( self.mother.fractal_object.settings['save_filename'][1] [:len(self.mother.fractal_object.settings['save_filename'][1] ) - 4] + '_batch.txt', 'w') else: if os.path.isfile(os.getcwd().replace('\\', '/') + "/save/recent_settings_batch.txt"): os.replace("/save/recent_settings.txt", "/save/recent_settings_old_batch.txt") f = open( os.getcwd().replace('\\', '/') + '/save/recent_settings_batch.txt', 'w') json.dump(self.batch_data_values, f) # f.write('{') # for index, key in enumerate(self.batch_data.keys()): # if index == len(self.batch_data)-1: line = "'" + key + "':" + str(self.batch_data[key]) + "\n" #if statement to make sure a comma doesn't get placed on the last line # else: line = "'" + key + "':" + str(self.batch_data[key]) + ",\n" # f.write(line) # f.write('}') f.close() self.parent.text_out.write("\nBatch settings have been saved!") return def batch_settings_import_from_file(self, filename): try: name = filename[:len(filename) - 4] + "_batch.txt" self.batch_data_values = json.load(open(name)) self.batch_values_from_dict_to_GUI() self.parent.text_out.write("\nBatch settings have been loaded!") except: self.parent.text_out.write("\nFailed to load batch settings!") return ##-----------------## def batch_GUI_settings_to_dict(self): for key in self.batch_data.keys(): if key != 'image_number' and key != 'number_of_steps': self.batch_data_values[key] = [ float(self.batch_data[key].start_entry.get()), float(self.batch_data[key].end_entry.get()), self.batch_data[key].delta_check.get(), float(self.batch_data[key].delta.get()), self.batch_data[key].smooth_start_check.get(), self.batch_data[key].smooth_end_check.get(), self.batch_data[key].cycle_check.get(), float(self.batch_data[key].cycle_period.get()) ] self.batch_data[key].current_value = float( self.batch_data[key].start_entry.get()) else: self.batch_data_values[key] = int(self.batch_data[key]) def batch_values_from_dict_to_GUI(self): for key in self.batch_data: if key != 'image_number' and key != 'number_of_steps': self.batch_data[key].start_entry.delete(0, "end") self.batch_data[key].start_entry.insert( "end", str(self.batch_data_values[key][0])) self.batch_data[key].end_entry.delete(0, "end") self.batch_data[key].end_entry.insert( "end", str(self.batch_data_values[key][1])) self.batch_data[key].delta.delete(0, "end") self.batch_data[key].delta.insert( "end", str(self.batch_data_values[key][3])) self.batch_data[key].cycle_period.delete(0, "end") self.batch_data[key].cycle_period.insert( "end", str(self.batch_data_values[key][7])) if self.batch_data[key].delta_check.get( ) != self.batch_data_values[key][2]: self.batch_data[key].delta_check.invoke() if self.batch_data[key].smooth_start_check.get( ) != self.batch_data_values[key][4]: self.batch_data[key].smooth_start_check.invoke() if self.batch_data[key].smooth_end_check.get( ) != self.batch_data_values[key][5]: self.batch_data[key].smooth_end_check.invoke() if self.batch_data[key].cycle_check.get( ) != self.batch_data_values[key][6]: self.batch_data[key].cycle_check.invoke() self.number_of_steps_entry.delete(0, "end") self.number_of_steps_entry.insert( "end", str(self.batch_data_values['number_of_steps'])) self.image_numbering_entry.delete(0, "end") self.image_numbering_entry.insert( "end", str(self.batch_data_values['image_number'])) def batch_thread(self): #self.mother.fractalobject.settings = self.mother.window1_object.GUI_settings_to_dict() self.batch_GUI_settings_to_dict() self.save_batch_settings() self.begin_batch_button.config(state="disabled") t = threading.Thread(target=self.batch_it) t.daemon = True t.start() def get_settings_from_fractal_object(self): self.mother.fractal_object.settings = self.mother.window1_object.GUI_settings_to_dict( ) for key in self.mother.fractal_object.settings: if key in self.batch_data: self.batch_data[key].start_entry.delete(0, "end") self.batch_data[key].start_entry.insert( "end", str(self.mother.fractal_object.settings[key][1])) self.batch_GUI_settings_to_dict() def batch_it(self): #sounds like "bat shit" number_of_steps = int(self.number_of_steps_entry.get()) self.batch_GUI_settings_to_dict() def batch_step(which_step): # batch data legend => [value,start,end,delta amount,delta toggle,smooth start,smooth end,cycle toggle,cycle period steps] for parameter in self.batch_data.keys(): if parameter != 'image_number' and parameter != 'number_of_steps': # print("parameter: " + str(parameter)) if self.batch_data[parameter].delta_check.get() == 1: self.batch_data[ parameter].current_value = self.batch_data_values[ parameter][ 0] + which_step * self.batch_data_values[ parameter][3] else: if (self.batch_data[parameter].smooth_start_check.get( ) != 1) and (self.batch_data[parameter]. smooth_end_check.get() != 1) and (self.batch_data[parameter]. cycle_check.get() != 1): self.batch_data[ parameter].current_value = which_step * ( self.batch_data_values[parameter][1] - self.batch_data_values[parameter][0] ) / self.batch_data[ 'number_of_steps'] + self.batch_data_values[ parameter][0] # update mother.fractal_object settings # recall, mother.fractal_object.settings[x][0] is the data type, and [x][1] is the value if self.mother.fractal_object.settings[parameter][ 0] == 'int': self.mother.fractal_object.settings[parameter][ 1] = int(self.batch_data[parameter].current_value) if self.mother.fractal_object.settings[parameter][ 0] == 'float': self.mother.fractal_object.settings[parameter][ 1] = self.batch_data[parameter].current_value self.mother.fractal_object.settings['image_name'][ 1] = self.mother.fractal_object.settings['image_name'][ 1][:len(self.mother.fractal_object. settings['image_name'][1]) - 4] + "-" + str( self.batch_data["image_number"]) + ".png" self.batch_data["image_number"] += 1 starting_image_name = self.mother.fractal_object.settings[ 'image_name'][1] for i in range(0, number_of_steps): self.mother.fractal_object.t = time.clock() self.mother.fractal_object.save_settings() batch_step(i + 1) self.mother.window1_object.values_from_object_to_GUI() self.mother.fractal_object.compute() self.mother.fractal_object.settings['image_name'][ 1] = starting_image_name self.begin_batch_button.config(state="normal") return
class TreeViewWindow: """ Класс отвечающий за окно просмотра запросов """ def __init__(self, method: str = 'view', completion_name: str = None, entry_pk: object = None): """ Запуск окна просмотра запросов :param method: метод просмотра (view-обычный просмотр всех запросов) :param completion_name: имя запроса default: None :param entry_pk: виджет Entry для записи выбранного pk default: None """ self.method = method self.completion_name = completion_name self.entry_pk = entry_pk self.select = ['pk', 'type_request', 'count_people', 'time_request'] self.get_requests_db = GetRequestsToDB() self.values = [] self.window = Toplevel() self.initialize_ui() left_frame = ttk.Frame(self.window) left_frame.grid(row=0, column=0, sticky='NSWE') right_frame = ttk.Frame(self.window, padding=5) right_frame.grid(row=0, column=1, sticky='NSWE') self.tree_view = ttk.Treeview(left_frame, columns=('Тип', 'Количество id', 'Дата')) self.tree_view.heading('#0', text='Дата') self.tree_view.heading('#1', text='Тип') self.tree_view.heading('#2', text='Количество id') self.tree_view.heading('#3', text='ID') self.tree_view.column('#0', minwidth=200, width=200, stretch=0) self.tree_view.column('#1', minwidth=200, width=220, stretch=0) self.tree_view.column('#2', minwidth=50, width=130, stretch=0, anchor='center') self.tree_view.column('#3', minwidth=100, width=100, stretch=0, anchor='center') self.tree_view.grid(row=0, column=0, columnspan=4, rowspan=3, sticky='NSEW') if method == 'view': btn_clear = ttk.Button(right_frame, text='Очистить') btn_delete = ttk.Button(right_frame, text='Удалить') btn_download = ttk.Button(right_frame, text='Выгрузить txt') btn_clear.grid(row=0, column=0, sticky='WE') btn_delete.grid(row=1, column=0, pady=5, sticky='WE') btn_download.grid(row=2, column=0, sticky='WE') btn_clear.bind('<Button-1>', lambda event: self.clear_values()) btn_delete.bind('<Button-1>', lambda event: self.delete_value()) btn_download.bind('<Button-1>', lambda event: self.download_on_txt()) else: btn_choose = ttk.Button(right_frame, text='Выбрать') btn_cancel = ttk.Button(right_frame, text='Отмена', command=lambda: self.window.destroy()) btn_choose.grid(row=0, column=0, sticky='SWE') btn_cancel.grid(row=1, column=0, sticky='SWE', pady=5) btn_cancel.bind('<Button-1>', lambda event: self.cancel()) btn_choose.bind('<Button-1>', lambda event: self.choose_value_for_parsing()) self.tree_view.bind('<Double-Button-1>', lambda event: self.choose_value_for_parsing()) self.window.rowconfigure(0, weight=1) self.window.columnconfigure(0, weight=9) self.window.columnconfigure(1, weight=1) left_frame.rowconfigure(0, weight=1) left_frame.columnconfigure(0, weight=1) self.__get_records__() self.completion_tree_view() def initialize_ui(self): """ Инициализация окна :return: """ FPVK = ImageTk.PhotoImage( file=os.path.join(path_to_dir_ico, 'FPVK.ico')) styles.set_global_style(self.window) w = 800 h = 600 self.window.title('Основные запросы') set_position_window_on_center(self.window, width=w, height=h) self.window.tk.call('wm', 'iconphoto', self.window._w, FPVK) def choose_value_for_parsing(self): """ Функция отвечающая за обработку двойного клика в случае выбора записи :return: """ try: pk = self.get_choose_value()['pk'] except IndexError: return self.entry_pk.delete(0, 'end') self.entry_pk.insert('end', str(pk)) del self.values self.window.destroy() def cancel(self): """ Кнопка отмены выбора pk :return: """ self.entry_pk.delete(0, 'end') del self.values self.window.destroy() def get_choose_value(self): """ Получить объект выбранной записи :return: """ if not self.tree_view.selection(): raise IndexError('не выбран элемент') item = self.tree_view.selection()[0] values = self.tree_view.item(item, option="values") result = {'pk': values[2], 'method': values[0], 'count': values[1]} return result def completion_tree_view(self): """ Функция заполняет TreeView данным из BaseData :return: """ if len(self.values) == 0: return if type(self.values) == dict: self.values = [self.values] index = 0 for item in self.values: time = gmtime(int(item['time_request'])) data = strftime(FORMAT_DATE, time) self.tree_view.insert('', index=index, text=data, values=(item['type_request'], item['count_people'], item['pk'])) index += 1 def clear_values(self): """ Очищает все записи в BD :return: """ ask = askyesno('Очистка записей', 'Вы уверены, что хотите удалить все записи?') if ask is True: LOGGER.warning('Запрос на удаление таблицы GetRequestsApi') delete_request_db = DeleteRequestsToDB() delete_request_db.delete_all_records( delete_request_db.get_requests) delete_request_db.delete_all_records( delete_request_db.additional_get_requests) self.window.destroy() def delete_value(self): """ Удаляет выбранную запись :return: """ try: values = self.get_choose_value() pk = values['pk'] LOGGER.warning( 'Запрос на удаление элемента в таблице GetRequestsApi') delete_request_db = DeleteRequestsToDB() delete_request_db.delete_record_in_bd( tb_name=delete_request_db.get_requests, where=f'pk={pk}') delete_request_db.delete_record_in_bd( tb_name=delete_request_db.additional_get_requests, where=f'pk_attachment={pk}') except IndexError as error: if str(error) == 'не выбран элемент': return for row in self.tree_view.get_children(): self.tree_view.delete(row) del self.values gc.collect() self.__get_records__() self.completion_tree_view() def download_on_txt(self): """ Выгрузка ID в txt формате :return: """ try: values = self.get_choose_value() except IndexError: return pk = values['pk'] __values__ = self.get_requests_db.get_records( tb_name=self.get_requests_db.get_requests, select=['response', 'type_request', 'last_parse'], where=f'pk={pk}', one_record=True) method = __values__['type_request'] last_parse = int(__values__['last_parse']) result = [] need_pk = False if __values__['response'] != REQUIRES_DATA: results = __values__['response'] results = json.loads(f'[{results}]') else: __values__ = self.get_requests_db.get_records( tb_name=self.get_requests_db.additional_get_requests, select=['pk'], where=f'pk_attachment={pk}', dictionary=False) results = [int(item[0]) for item in __values__] need_pk = True for pk in results: if need_pk is False: item = pk else: __item__ = self.get_requests_db.get_records( tb_name=self.get_requests_db.additional_get_requests, select=['response'], where=f'pk={pk}', one_record=True) item = __item__['response'] item = json.loads(f'[{item}]') if method == NAME_PARSING['by_groups']: if last_parse == 1: result += [str(i['id']) for i in item] else: result += [str(i) for i in item] else: result += [str(i) for i in item] del pk, item del results result = '\n'.join(result) directory = asksaveasfilename() if directory in ['', ' ']: del result gc.collect() return if directory[-4:] != '.txt': directory += '.txt' with open(directory, 'w', encoding='utf-8') as file: file.write(result) del result gc.collect() def __get_records__(self): if self.method == 'view': values = self.get_requests_db.get_records( select=self.select, order='pk DESC', tb_name=self.get_requests_db.get_requests, ) self.values = [] if len(values) == 0 else values else: self.entry_pk = self.entry_pk values = self.get_requests_db.get_records( select=self.select, order='pk DESC', tb_name=self.get_requests_db.get_requests, where=f' (type_request = "{self.completion_name}") ' 'and (last_parse = 1)') self.values = [] if len(values) == 0 else values
class Edit(Frame): # pylint: disable=too-many-ancestors """Class to edit a frame.""" def __init__(self, parent, filename, scm, gui): """Initialise.""" Frame.__init__(self, parent) self.parent = parent self.file = filename self.scm = scm self.gui = gui self.edit_win = Toplevel(self.master) self.edit_win.title("SCM Helper - Edit Config") top_frame = Frame(self.edit_win) top_frame.grid(row=0, column=0, sticky=W + E) abtn = Button(top_frame, text="Save", command=self.save_command) abtn.grid(row=0, column=0, pady=10, padx=10) cbtn = Button(top_frame, text="Close", command=self.on_exit) cbtn.grid(row=0, column=1, pady=10, padx=10) top_group = LabelFrame(self.edit_win, text=filename, pady=5, padx=5) top_group.grid(row=1, column=0, columnspan=2, pady=10, padx=10, sticky=NSEW) self.edit_win.columnconfigure(0, weight=1) self.edit_win.rowconfigure(1, weight=1) top_group.columnconfigure(0, weight=1) top_group.rowconfigure(0, weight=1) self.text_pad = scrolledtext.ScrolledText(top_group, width=80, height=40) self.text_pad.grid(row=0, column=0, sticky=NSEW) with open(self.file, FILE_READ, encoding="utf8") as file: contents = file.read() self.text_pad.insert("1.0", contents) file.close() self.text_pad.edit_modified(False) self.edit_win.protocol("WM_DELETE_WINDOW", self.on_exit) def on_exit(self): """Close.""" if self.text_pad.edit_modified(): title = "SCM-Helper: Save Config" msg = "Save Config?" resp = messagebox.askyesno(title, msg, parent=self.edit_win) if resp: if self.save_command() is False: return self.edit_win.destroy() def save_command(self): """Save.""" with open(self.file, FILE_WRITE, encoding="utf8") as file: # slice off the last character from get, as an extra return is added data = self.text_pad.get("1.0", END) file.write(data) file.close() self.gui.notify_text.config(state=NORMAL) if self.scm.get_config_file() is False: msg = "Error in config file - see status window for details." messagebox.showerror("Error", msg, parent=self.parent) self.gui.notify_text.config(state=DISABLED) return False self.text_pad.edit_modified(False) self.gui.notify_text.config(state=DISABLED) return True
class SpeciesListDialog: def __init__(self, parent): self.parent = parent self.gui = Toplevel(parent.guiRoot) self.gui.grab_set() self.gui.focus() self.gui.columnconfigure(0, weight=1) self.gui.rowconfigure(1, weight=1) Label(self.gui, text="Registered Species:").grid(row=0, column=0, pady=5, padx=5, sticky="w") self.listRegisteredSpecies = Listbox(self.gui, width=70) self.buttonAdd = Button(self.gui, text=" + ") self.buttonDel = Button(self.gui, text=" - ") self.listRegisteredSpecies.grid(row=1, column=0, columnspan=3, sticky="nswe", pady=5, padx=5) self.buttonAdd.grid(row=2, column=1, pady=5, padx=5) self.buttonDel.grid(row=2, column=2, pady=5, padx=5) # Set (minimum + max) Window size self.gui.update() self.gui.minsize(self.gui.winfo_width(), self.gui.winfo_height()) # self.gui.maxsize(self.gui.winfo_width(), self.gui.winfo_height()) self.actionUpdate(None) self.gui.bind("<<Update>>", self.actionUpdate) self.gui.protocol("WM_DELETE_WINDOW", self.actionClose) self.buttonDel.bind("<ButtonRelease>", self.actionDel) self.buttonAdd.bind("<ButtonRelease>", self.actionAdd) self.gui.mainloop() def actionClose(self): self.parent.guiRoot.event_generate("<<Update>>", when="tail") self.gui.destroy() def actionUpdate(self, event): self.listRegisteredSpecies.delete(0, "end") for (taxid, name) in self.parent.optimizer.speciesList: self.listRegisteredSpecies.insert("end", taxid + ": " + name) def actionDel(self, event): try: selection = self.listRegisteredSpecies.selection_get() selectionSplit = selection.split(": ") self.parent.optimizer.speciesList.remove((selectionSplit[0], selectionSplit[1])) self.gui.event_generate("<<Update>>") except tkinter.TclError: # no selection pass def actionAdd(self, Event): SpeciesSearchDialog(self.parent, self)