def openBank(bankData, CID): print(f"CID: {CID}") win2 = tk.Toplevel() win2.geometry("300x400") userCID_label = ttk.Label(win2, text=f"User: "******"light blue", font=("TkDefaultFont", 16)) userCID_label.grid(row=1, column=0, sticky=W, pady=10, padx=3) userCIDValue_label = ttk.Label(win2, text=str(CID), background="light blue", font=("TkDefaultFont", 16)) userCIDValue_label.grid(row=1, column=1, sticky=W, pady=10, padx=3) # Listbox view bankInfo_label = ttk.Label(win2,text="bid cid bank-name account-number ", font=("TkDefaultFont", 10)) bankInfo_label.grid(row=2, column=0, columnspan=3) list_box = Listbox(win2, height=6, font="helvetica 13", bg="light gray") list_box.grid(row=3, column=0, columnspan=2, sticky=W + E) list_box.delete(0, 'end') for row in bankData: list_box.insert('end', row) bankName_label = ttk.Label(win2, text="Bank Name: ", background="light blue", font=("TkDefaultFont", 16)) bankName_label.grid(row=4, column=0, sticky=W, pady=10, padx=3) bankName_text = StringVar() bankName_input = ttk.Entry(win2, width=10, textvariable=bankName_text, font=("TkDefaultFont", 12)) bankName_input.grid(row=4, column=1, sticky=W) accountNumber_label = ttk.Label(win2, text="Account Number: ", background="light blue", font=("TkDefaultFont", 16)) accountNumber_label.grid(row=5, column=0, sticky=W, pady=10, padx=3) accountNumber_text = StringVar() accountNumber_input = ttk.Entry(win2, width=10, textvariable=accountNumber_text, font=("TkDefaultFont", 12)) accountNumber_input.grid(row=5, column=1, sticky=W) submit_btn = Button(win2, text="Add", bg="green", fg="white", font="helvetica 10 bold", command=lambda: bank_insert(win2,int(CID), bankName_text.get(), accountNumber_text.get())) submit_btn.grid(row=6, column=1) bid_label = ttk.Label(win2, text="BID: ", background="light blue", font=("TkDefaultFont", 16)) bid_label.grid(row=7, column=0, sticky=W, pady=10, padx=3) bid_combo = ttk.Combobox(win2, width=8, state="readonly", font=("TkDefaultFont", 12)) bid_combo.grid(row=7, column=1, sticky=W) values = [] #gets all the bid values and puts them into a combobox for x in bankData: values.append(x[0]) bid_combo['values'] = values remove_btn = Button(win2, text="Remove", bg="red", fg="white", font="helvetica 10 bold", command=lambda: bank_remove(win2, bid_combo.get())) remove_btn.grid(row=8, column=1)
class ScenarioCenter(Toplevel): def __init__(self, parent, scEvents, scName): super().__init__(parent, height=100) self.parent = parent self.attributes('-topmost', 'true') self.resizable(width=False, height=False) self.title('Scenario Center') self.scEvents = scEvents self.scName = scName editListFrame = Frame(self) editListFrame.pack() self.currentSelection = [] self.lb = Listbox(editListFrame, selectmode=MULTIPLE) for i in self.scEvents: self.lb.insert(END, i) self.lb.bind("<<ListboxSelect>>", self.onSelect) self.lb.grid(row=0, column=0, columnspan=2) self.DeleteBtn = Button(editListFrame, text='Delete', width=12, height=1) self.DeleteBtn.grid(row=0, column=2, padx=5) self.DeleteBtn.bind('<ButtonRelease-1>', self.onDeleteClick) self.cancelBtn = Button(editListFrame, text='Cancel', width=12, height=1) self.cancelBtn.grid(row=1, column=1, pady=2) self.cancelBtn.bind('<ButtonRelease-1>', self.onCancelClick) self.okBtn = Button(editListFrame, text='OK', width=12, height=1) self.okBtn.grid(row=1, column=2, padx=1, pady=2) self.okBtn.bind('<ButtonRelease-1>', self.onOkClick) def onCancelClick(self, event): log.deleteScenarioFile(self.scName) self.parent.updateList() self.destroy() def onDeleteClick(self, event): print(self.scEvents) self.lb.delete(0, END) for idx in self.currentSelection[::-1]: del self.scEvents[idx] for i in self.scEvents: self.lb.insert(END, i) def onOkClick(self, event): log.saveSelectedScenario(self.scName, self.scEvents) self.destroy() def onSelect(self, event): self.currentSelection = list(self.lb.curselection())
def open_query(): """Opens the Query TopLevel window""" query_window = Toplevel(root) query_window.title("Query") global entity entity = Listbox(query_window, selectmode="single", width=70) entity.grid(row=0, column=1) options = sf.query_all( ("SELECT ID, QualifiedAPIName from EntityDefinition" " order by QualifiedAPIName") ) optionList = [] entity.delete(0, END) for record in options['records']: optionList.append(record['QualifiedApiName']) for each_item in range(len(optionList)): entity.insert(END, optionList[each_item]) show_fields = Button( query_window, text="Show Fields", command=extract_fields ) show_fields.grid(row=1, column=1) global fields fields = Listbox(query_window, selectmode="multiple", width=70) fields.grid(row=2, column=1) create_query = Button( query_window, text="Create Query", command=write_query ) create_query.grid(row=4, column=1) global soql soql = Text(query_window, width=70, height=5) soql.grid(row=5, column=1) soql.insert(END, " ") global folder folder = Label(query_window, text="Select Folder") folder.grid(row=6, column=1) button_browse = Button( query_window, text="Browse", command=browse_button ) button_browse.grid(row=7, column=1) global file file = Entry(query_window, width=70) file.grid(row=8, column=1) Label(query_window, text=" ").grid(row=9, column=1) button_extract = Button( query_window, height=1, width=15, text="Extract", command=extract ) button_extract.grid(row=10, column=1)
def load_links(self, tkList: tk.Listbox): tkList.delete(0, "end") filename = filedialog.askopenfilename(initialdir="/", title="Select your playlist", filetypes=[("text files", "*.txt")]) with open(filename, "r") as file: data = file.read().split("\n") tkList.insert("end", *data)
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 Page1(Frame): def on_recommend_btn_click(self): selected_index = self.item_lst_box.curselection() user_preferences = [ self.item_lst_box.get(indx) for indx in selected_index ] print(f'User preferences are {user_preferences}') if len(user_preferences) > 3: messagebox.showwarning( "Warning", "Currently doesnt support for than 3 preferences") else: self.business_logic.set_preferences(user_preferences) Page2(self.master, self).show() def get_appliances(self): selected = self.radio_btn_var.get() print(f'Selected option is {selected}') if selected in (0, 1): self.business_logic.set_choice(selected) for index, item in enumerate(self.business_logic.items[ self.business_logic.selected_choice]): self.item_lst_box.insert(index, item) self.recommend_btn.configure(state=ACTIVE) else: self.recommend_btn.configure(state=DISABLED) self.item_lst_box.delete(0, 'end') def __init__(self, master): super().__init__(master, relief='flat', borderwidth=40) self.business_logic = MLLogic() self.radio_btn_var = IntVar() self.master.title(self.business_logic.title) self.pack(fill=None, expand=False) Label(self, text="Select the type of appliances you want to buy").grid( row=1, columnspan=2, sticky='NW') for index, appliance_type in enumerate( self.business_logic.appliance_choices): rdo_btn = Radiobutton(self, text=appliance_type, variable=self.radio_btn_var, value=index, command=self.get_appliances) rdo_btn.select() rdo_btn.grid(row=index + 2, column=2) Label(self, text="Preferences").grid(row=7, columnspan=2, sticky='NW') self.item_lst_box = Listbox(self, selectmode='multiple') self.item_lst_box.delete(0, 'end') self.item_lst_box.grid(row=7, column=2) self.recommend_btn = Button(self, text='Recommend', command=self.on_recommend_btn_click) self.recommend_btn.grid(row=9, column=2, sticky='NW') self.recommend_btn.configure(state=DISABLED)
class EntryOptionsWindow: def __init__(self, ls: str, tk: Tk, select_path=False) -> None: self.select_path = select_path self.List = ls self.Tk = tk self.Root = Toplevel(self.Tk) self.Root.withdraw() self.Frame = Frame(self.Root) self.Box = Listbox(self.Frame, selectmode='extended', width=54, height=24) for i in globals()[self.List]: self.Box.insert(END, i) self.Scroll = Scrollbar(self.Frame, command=self.Box.yview) self.Entry = Entry(self.Frame) self.ButtonAdd = Button(self.Frame, text='Добавить', command=self.__add_item) self.ButtonDel = Button(self.Frame, text='Удалить', command=self.__del_item) self.ButtonDone = Button(self.Frame, text='Готово', command=self.__save_list) self.ButtonExit = Button(self.Frame, text='Отмена', command=self.Root.destroy) def __add_item(self) -> None: if self.select_path: text = filedialog.askdirectory() else: text = self.Entry.get() if text: self.Box.insert(END, text) self.Entry.delete(0, END) def __del_item(self) -> None: select = list(self.Box.curselection()) select.reverse() for i in select: self.Box.delete(i) def __save_list(self) -> None: globals()[self.List] = list(self.Box.get(0, END)) self.Root.destroy() def main(self) -> None: center_win(self.Root, '500x400') self.Root.deiconify() self.Root.title(f'Editing {self.List}') self.Box.pack(side='left', expand=True) self.Scroll.pack(side='left', fill='y') self.Box.config(yscrollcommand=self.Scroll.set) self.Frame.pack(side='left', padx=10) if not self.select_path: self.Entry.pack(anchor='n') self.ButtonAdd.pack(fill='x') self.ButtonDel.pack(fill='x') self.ButtonDone.pack(fill='x') self.ButtonExit.pack(fill='x') self.Root.mainloop()
class LabeledListBox(Frame): def __init__(self, parent, list_model, label_text): Frame.__init__(self, parent) self._list_model = list_model self._list_objects = [] self._selected_items = [] scrollbar = Scrollbar(self, orient=VERTICAL) Label(self, text=label_text).pack() self.listbox = Listbox(self, selectmode=EXTENDED, exportselection=0, yscrollcommand=scrollbar.set, borderwidth=0, highlightthickness=0) scrollbar.config(command=self.listbox.yview) scrollbar.pack(side=RIGHT, fill=Y) self.listbox.pack(side=LEFT, fill=BOTH, expand=1) self.listbox.bind('<<ListboxSelect>>', self._on_select) self._list_model.list_items_model.add_listener(self._list_items_changed) self._list_model.selected_items_model.add_listener(self._selected_items_changed) self._update_list_items() def _list_items_changed(self, values): self._update_list_items() def _selected_items_changed(self, values): self._update_selected_items() def _update_list_items(self): values, labels = self._list_model.list_items_model.get_list_values() if not values == self._list_objects: self._list_objects = [] self._selected_items = [] self.listbox.delete(0, END) for value, label in zip(values, labels): self._list_objects.append(value) self.listbox.insert(END, label) self._update_selected_items() def _update_selected_items(self): selected_items = self._list_model.selected_items_model.selected_items if not selected_items == self._selected_items: self._selected_items = selected_items for index, list_item in enumerate(self._list_objects): if list_item in selected_items: self.listbox.selection_set(index) def _on_select(self, evt): visible_selected_indices = self.listbox.curselection() for index, list_item in enumerate(self._list_objects): if index in visible_selected_indices: self._list_model.selected_items_model.select(list_item) else: self._list_model.selected_items_model.deselect(list_item)
class CollectionFrame(Frame): """ Frame permétant de gérer la collection d'épisodes. """ def __init__(self, master=None, select_callback=None, delete_callback=None): Frame.__init__(self, master) self._select_callback = select_callback self._delete_callback = delete_callback choices = Variable(self) self.listbox = Listbox(self, listvariable=choices, selectmode='single') self.listbox.pack() buttons_frame = Frame(self) Button(buttons_frame, text="Select", command=self.get_selected_element).pack(side=RIGHT) Button(buttons_frame, text="Delete", command=self.delete_selected_element).pack(side=RIGHT) buttons_frame.pack() def add_element(self, element, index=END): """ Ajoute un épisode dans la liste. L'index permet d'ordonner les épisodes. :param element: Titre de l'épisode :param index: indice d'insertion :return: None """ self.listbox.insert(index, element) def get_selected_element(self): curselection = self.listbox.curselection() if len(curselection) != 1: print("Pas de selection") else: self._select_callback(curselection[0]) def delete_selected_element(self): curselection = self.listbox.curselection() if len(curselection) != 1: print("Pas de selection") else: ep_index = curselection[0] self.listbox.delete(ep_index) self._delete_callback(ep_index)
class LoadGUI(Frame): """Loading frame which allows the users to pick quizzes. """ def __init__(self, master=None): Frame.__init__(self, master) self.grid(row=0, column=0, sticky="nsew") self.grid_columnconfigure(0, weight=1) self.cover_photo = PhotoImage(file="static/cover.png") self.cover_label = Label(self, image=self.cover_photo) self.cover_label.grid(row=0, column=0, padx=(20,20), pady=(20,10), sticky="ew") self.select_frame = LabelFrame(self, text="Select a quiz") self.select_frame.grid(row=1, column=0, padx=(20,20), pady=(10,20), sticky="ew") for i in range(0,4): self.select_frame.grid_rowconfigure(i, weight=1) self.select_frame.grid_columnconfigure(0, weight=4) self.select_frame.grid_columnconfigure(1, weight=1) self.quiz_list = Listbox(self.select_frame) self.quiz_list.grid(row=0, column=0, rowspan=4, padx=(10,10), pady=(10,10), sticky="ew") self.start_button = Button(self.select_frame, text="Start quiz", command=self.start_chosen) self.start_button.grid(row=0, column=1, padx=(0,10), pady=(10,5), sticky="nsew") self.refresh_button = Button(self.select_frame, text="Refresh list", command=self.refresh) self.refresh_button.grid(row=1, column=1, padx=(0,10), pady=(5,5), sticky="nsew") self.help_button = Button(self.select_frame, text="Help", command=var.HELP_URL) self.help_button.grid(row=2, column=1, padx=(0,10), pady=(5,5), sticky="nsew") self.quit_button = Button(self.select_frame, text="Quit", command=root.destroy) self.quit_button.grid(row=3, column=1, padx=(0,10), pady=(5,10), sticky="nsew") self.get_quizzes() def get_quizzes(self): """[summary] """ self.dir_list = sorted([i[:-5] for i in os.listdir() if i.endswith(".json") and "quiz" in i.lower()]) for f in self.dir_list: self.quiz_list.insert("end", f) def refresh(self): """[summary] """ self.quiz_list.delete(0, "end") self.get_quizzes() def start_chosen(self): """[summary] """ self.filename = self.quiz_list.get("active") + ".json" file_handler.parse_file(self.filename) file_handler.parse_leaderboard() quiz_gui.add_questions() quiz_gui.tkraise()
def show_items(self, list_of_items: list, target_box: Listbox, check_original: bool): target_box.delete(0, END) index = 0 for item in list_of_items: target_box.insert(END, item) if check_original and not self.files_map.get(item): self.source_files_box.itemconfig(index, {'fg': 'gray50'}) target_box.itemconfig(index, {'fg': 'red'}) elif check_original and self.files_map.get(item): self.source_files_box.itemconfig(index, {'fg': 'black'}) target_box.itemconfig(index, {'fg': 'black'}) index += 1 scroll_position = ('moveto', self.scroll_bar_position[0]) self.source_files_box.yview(*scroll_position) self.result_files_box.yview(*scroll_position)
class MainWindow: def __init__(self, vehicles): self.vehicles = vehicles self.root = Tk() self.root.title("GUI на Python") self.root.geometry("300x250") self.file_menu = Menu() self.file_menu.add_command(label="New", command=self.new_win) self.file_menu.add_command(label="Save", command=self.show_list) self.file_menu.add_command(label="Open", command=self.open_file) self.file_menu.add_separator() self.file_menu.add_command(label="Exit") self.main_menu = Menu() self.main_menu.add_cascade(label="File", menu=self.file_menu) self.main_menu.add_cascade(label="Edit") self.main_menu.add_cascade(label="View") self.languages_listbox = Listbox() self.languages_listbox.pack(expand=True, fill=BOTH) self.root.config(menu=self.main_menu) self.root.mainloop() def get_list_text_from_file(self, filename): arr_text = [] with open(filename, "r") as file_data: for line in file_data: arr_text.append(line) return arr_text def open_file(self): filename = filedialog.askopenfilename() values = self.get_list_text_from_file(filename) for value in values: self.languages_listbox.insert(END, value) def new_win(self): n_win = MainWindow(vehicles) def show_list(self): self.languages_listbox.delete(0, self.languages_listbox.size()) for value in vehicles: self.languages_listbox.insert(END, value)
class List: def __init__(self, root, array=[]): self.__root = root self.__frame = Frame(self.__root) self.__scrollBar = Scrollbar(self.__frame) self.__list = Listbox(self.__frame, font=12, selectmode=SINGLE, width=10, yscrollcommand=self.__scrollBar.set) self.__list.config(width=40) self.__list.pack(side=LEFT, anchor=W, fill=BOTH, expand=True) self.__lessons = [] self.setList(array) self.__scrollBar.config(command=self.__list.yview) self.__scrollBar.pack(side=RIGHT, fill=Y) self.__frame.pack(side=LEFT, anchor=W, fill=BOTH, expand=True) def getObjectList(self): return self.__list def setList(self, array=[]): self.__deleteAll() self.__lessons = [x for x in array] for item in array: self.__list.insert(END, str(item)) def getSelectedElement(self, e=None): if self.__list.curselection() is (): return None else: return self.__lessons[self.__list.curselection()[0]] def setSelectedItem(self, i): self.__list.activate(i) def __deleteAll(self): self.__list.delete(0, END)
class ServerRunningView(View): WINDOW_TITLE = "Chadt Server" LABEL_TEXT = "Connected Clients:" CHAT_HEIGHT = 10 CHAT_WIDTH = 80 def __init__(self): super().__init__(self.WINDOW_TITLE) self.label = None self.user_list = None self.chat_log = None self.chat_scroll = None self._initialize_widgets() self._place_widgets() def _initialize_widgets(self): self.label = Label(self.root, text=self.LABEL_TEXT) self.user_list = Listbox(self.root) self.chat_log = Text(self.root, height=self.CHAT_HEIGHT, width=self.CHAT_WIDTH) self.chat_log.bind("<Key>", lambda x: "break") # this^ bind effectively makes the text widget read-only self.chat_scroll = Scrollbar(self.root, command=self.chat_log.yview) self.chat_log["yscrollcommand"] = self.chat_scroll.set def _place_widgets(self): self.label.grid(row=0, column=0) self.user_list.grid(row=1, column=0) self.chat_log.grid(row=1, column=1) def update_list_box(self, items): self.user_list.delete(0, END) for item in items: self.user_list.insert(END, item) def display_new_text_message(self, message): self.chat_log.insert(END, message + "\n") self.chat_log.see(END)
class AddWindow(Tk): def __init__(self, parent_window): super().__init__() self.title("add schedule") self.entry = Entry(self) self.entry.grid(row=0, column=0, columnspan=2) self.entry.bind("<Key>", self.key_typed) self.listBox = Listbox(self) for i in WebExtractionHelper.get_hint(""): self.listBox.insert(END, i) self.listBox.grid(row=1, column=0, columnspan=2) self.cancel_button = Button(self, text='cancel', command=self.cancel) self.cancel_button.grid(row=2, column=0) self.selected_button = Button(self, text='select', command=self.selected) self.selected_button.grid(row=2, column=1) self.parent_window = parent_window def key_typed(self, event: EventType): self.listBox.delete(0, END) postfix = '' if event.char.isdigit() or event.char.isalpha(): postfix = event.char hints = WebExtractionHelper.get_hint(self.entry.get() + postfix) for hint in hints: self.listBox.insert(END, hint) def cancel(self): self.destroy() def selected(self): try: name: str = self.listBox.get(self.listBox.curselection()) FileExtractionHelper.put_to_file(name) except TclError: pass self.destroy() self.parent_window.rerender_list()
class Output(Frame): def __init__(self, parent, *args, **kwargs): super(Output, self).__init__(parent, *args, **kwargs) self.create_list() self.pack_propagate(False) def create_list(self): self.listbox = Listbox(self) scroll = Scrollbar(self, orient='vertical', command=self.listbox.yview) self.listbox.configure(yscrollcommand=scroll.set) self.listbox.pack(side='left', fill='both', expand=True) scroll.pack(side='left', fill='y') def insert(self, value): self.listbox.insert('end', str(value)) def clear(self): self.listbox.delete(0, 'end')
class updating_box(): def __init__(self, root, widget, li, gridx, gridy): self.li = li self.widget = widget gridx = gridx gridy = gridy self.basic_frame = ttk.Frame(root) self.basic_frame.grid(row=gridx, column=gridy) self.input_entry = ttk.Entry(self.basic_frame, textvariable=self.widget) self.input_entry.grid(row=0, column=1) self.lb = Listbox(self.basic_frame, width=20, height=4) self.lb.insert(0, *self.li) self.input_entry.bind('<KeyRelease>', lambda e: self.update_list()) self.lb.bind('<Return>', lambda e: self.selected_item()) self.lb.bind('<Double-Button-1>', lambda e: self.selected_item()) self.input_entry.bind('<Button-1>', lambda e: self.show_me()) self.input_entry.bind('<Return>', lambda e: self.hide_me()) def hide_me(self): self.lb.grid_forget() def show_me(self): self.lb.grid(row=1, column=1) def update_list(self): temp = list( filter( lambda x: x if self.widget.get().lower() in x.lower() else '', self.li)) self.lb.delete(0, END) self.lb.insert(0, *temp) def selected_item(self): for i in self.lb.curselection(): self.widget.set(self.lb.get(i)) self.lb.tk_focusNext().focus() self.lb.grid_forget()
class SeeExamNotes(): def __init__(self, frame, column, id_user): self.frame = frame self.column = column self.id_user = id_user self.created() self.mounted() def created(self): self.labelTittle = Label(self.frame, text='Ver notas de postulaciones') self.labelTittle.grid(column=self.column, row=0, pady=15) self.labelPostulations = Label(self.frame, text='elige la asignatura que quieres ver la nota') self.labelPostulations.grid(column=self.column, row=1, pady=5) self.comboBoxSubjects = ttk.Combobox(self.frame) self.comboBoxSubjects.grid(column=self.column, row=2, pady=5) self.buttonSelecSubject = Button(self.frame, text='Select Subject', command= lambda: self.showExams()) self.buttonSelecSubject.grid(column=self.column, row=3, pady=5) self.labelExams = Label(self.frame, text='Exams') self.labelExams.grid(column=self.column, row=4, pady=5) self.listboxExams = Listbox(self.frame, width=30) self.listboxExams.grid(column=self.column, row=5, pady=5) def mounted(self): self.subjectPostulations = getSubjectsByPostulant(self.id_user) listSubjectPostulation = [] for subject in self.subjectPostulations: listSubjectPostulation.append(subject[1]) self.comboBoxSubjects["values"] = listSubjectPostulation def showExams(self): self.listboxExams.delete(0, END) id_subject = self.subjectPostulations[self.comboBoxSubjects.current()][0] evaluations = getEvaluations(id_subject, self.id_user) print(evaluations) for evaluation in evaluations: self.listboxExams.insert(END, evaluation)
class Window(Tk): def __init__(self): Tk.__init__(self) self.state('zoomed') self.config(bg='#282a36') self.bind('<KeyPress>', self.manipula) self.tx = Texto(self) self.tx.bind('<Tab>', self.tabSpace) self.linhas = Listbox(self, width=10, bg='#21222c', fg='#ffffff', bd=0) self.status = Label(self, text='coluna: 1 linha: 1 arquivo: ', bg='#21222c', fg='#fff') self.tx.config(width=170, height=42, bg='#282a36', fg='#fffffe', bd=0) self.linhas.pack(side='left', fill='y') self.tx.pack(expand=True, anchor='ne') self.status.pack(expand=True, fill='x', anchor='se') def manipula(self, keypress): print(keypress) self.linha = float(self.tx.index('end-1c')) * 1 self.linha = str(self.linha) self.indice = self.linha.index('.') coluna = f' Cl: {self.linha[self.indice + 1:]}' linha = f' Ln: {self.linha[:self.indice]}' self.status['text'] = f'{coluna} {linha} {" " * 10}{__file__[10:-1]}' self.linhas.insert(int(self.linha[:self.indice]), str(self.linha[:self.indice])) self.removeLines() self.tecla = keypress def tabSpace(self, tab): self.tx.insert('end', f' ' * 4) return 'break' def removeLines(self): pos = str(self.tx.index('end')) ind = pos.index('.') pos = int(pos[:ind]) self.linhas.delete(pos - 1, 'end')
class ScrollList(Frame): def __init__(self, root, onSelect=None): Frame.__init__(self, root) self.selectAction = onSelect self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) self.xscroll = Scrollbar(self) self.yscroll = Scrollbar(self) self.list = Listbox(self) self.list.bind("<<ListboxSelect>>", self.onSelect) self.list.config(xscrollcommand=self.xscroll.set) self.list.config(yscrollcommand=self.yscroll.set) self.list.config(activestyle="none") self.list.config(exportselection=False) self.xscroll.config(orient="horizontal") self.xscroll.config(command=self.list.xview) self.yscroll.config(command=self.list.yview) self.list.grid(row=0, column=0, sticky="nesw") self.xscroll.grid(row=1, column=0, sticky="ew") self.yscroll.grid(row=0, column=1, sticky="ns") # set this list's data def setData(self, data): self.list.delete(0, "end") for item in data: self.list.insert("end", item) # get the currently selected index def getSelection(self): ind = self.list.curselection() return -1 if ind == () else int(ind[0]) # executed when a list item is selected def onSelect(self, event=None): if self.selectAction is not None: self.selectAction()
class mask_select(Frame): def __init__(self, controller, current_model : model_manager_obj, master, *args, **kwargs): self.controller = controller super().__init__(master, *args, **kwargs) self.listbox = Listbox(self, exportselection=False) self.listbox.pack(fill="both", expand=True) self.listbox.bind("<<ListboxSelect>>",self.selection) Label(self,text="New mask file: ").pack() self.entry_text = StringVar() Entry(self,textvariable=self.entry_text).pack() Button(self,text='Create',command=self.add_new).pack() self.update_model(current_model) def update_model(self, current_model): self.model = current_model self.mask_file_list = self.model.get_mask_file_list() self.current_mask_file=self.model.get_current_mask_file() self.listbox.delete(0, END) for item in self.mask_file_list: self.listbox.insert(END, item) self.listbox.select_set(0) self.listbox.event_generate("<<ListboxSelect>>") def selection(self,event): w = event.widget index = int(w.curselection()[0]) value = w.get(index) selected = value self.controller.event_change_mask_file(selected) pass def add_new(self): new = self.entry_text.get() self.controller.event_add_mask_file(new) pass
class MillipedeGUI: def __init__(self, master): self.master = master master.title("Simple Crawler") master.geometry("500x500") mainFrame = Frame(master=master,bg='white') mainFrame.pack_propagate(0) #Don't allow the widgets inside to determine the frame's width / height mainFrame.pack(fill=BOTH, expand=1) #Expand the frame to fill the root window self.label = Label(mainFrame, text="Type a URL") self.label.pack() # self.urlField = Text(mainFrame, height=1, width=30, borderwidth=1, relief=RAISED) self.urlField = Entry(mainFrame) self.urlField.pack() self.listBox = Listbox(mainFrame) self.listBox.pack() self.greet_button = Button(mainFrame, text="Crawl", command=self.crawl) self.greet_button.pack() self.close_button = Button(mainFrame, text="Close", command=master.quit) self.close_button.pack() def crawl(self): url = self.urlField.get() print(url) if url == "": print("No URL provided") return hrefs = Href(url) domains = hrefs.countHyperlinks() counter = 1 self.listBox.delete(0,'end') for domain in domains: self.listBox.insert(counter, domain + " - " + str(domains[domain])) counter += 1 print(domain, domains[domain])
class InfoList: def __init__(self, baseFrame, selectEvent, dataFormat, initialInfo=[], width=30, height=5): self.infoData = initialInfo self.dataFormat = dataFormat self.infoList = Listbox( baseFrame, width=width, height=height, listvariable=StringVar(value=[ele[0] for ele in self.infoData])) self.infoList.bind('<<ListboxSelect>>', selectEvent) self.infoList.grid(row=0, column=0) self.scrollbar = Scrollbar(baseFrame, orient=VERTICAL, command=self.infoList.yview) self.scrollbar.grid(row=0, column=1, sticky=(N, S)) self.infoList['yscrollcommand'] = self.scrollbar.set self.updateInfo(self.infoData) def updateInfo(self, infoData=[]): self.infoList.delete(0, len(self.infoData) - 1) self.infoData = infoData for iinfo, info in enumerate(self.infoData): info[0] = iinfo self.infoList.insert(iinfo, self.dataFormat(info)) for i in range(0, len(self.infoData), 2): self.infoList.itemconfigure(i, background='#f0f0ff') def report(self): idxs = self.infoList.curselection() if len(idxs) == 1: return self.infoData[idxs[0]] return []
class ContactList(Frame): def __init__(self, master, **kwargs): super().__init__(master, **kwargs) self.lb = Listbox(self) scroll = Scrollbar(self, command=self.lb.yview) self.lb.config(yscrollcommand=scroll.set) scroll.pack(side=RIGHT, fill=Y) self.lb.pack(side=LEFT, fill=BOTH) def insert(self, contact, index=END): self.lb.insert(index, "{} {}".format(contact.first_name, contact.last_name)) def delete(self, index): self.lb.delete(index) def edit(self, contact, index): self.delete(index) self.insert(contact, index) def double_click(self, fn): self.lb.bind('<Double-Button-1>', lambda _: fn(self.lb.curselection()[0]))
class Leaderboard(Frame): def __init__(self, parent, movies): Frame.__init__(self, parent) self.movies = movies scrollbar = Scrollbar(self, orient=VERTICAL) scrollbar.pack(side=RIGHT, fill=Y) self.listbox = Listbox(self, width=80, yscrollcommand=scrollbar.set, selectmode=EXTENDED) self.listbox.pack(expand=True, fill=Y) scrollbar.config(command=self.listbox.yview) self.load() def load(self): self.listbox.delete(0, END) count = 1 for movie in sorted(self.movies, reverse=True): self.listbox.insert( END, "{}. {} ({:.2f})".format(count, movie.name, movie.elo)) count += 1
class HOPSListDisplay(HOPSWidget): def __init__(self, window, font='Courier'): widget = Frame(window.main_frame) scrollbar = Scrollbar(widget) scrollbar.pack(side=RIGHT, fill=Y) self.listbox = Listbox(widget, yscrollcommand=scrollbar.set, font=font) self.listbox.pack(side=LEFT, fill=BOTH, expand=True) scrollbar.config(command=self.listbox.yview) window.root.columnconfigure(0, weight=1) window.root.rowconfigure(0, weight=1) HOPSWidget.__init__(self, window, widget, 'ListDisplay') def update_list(self, list_to_add): self.listbox.delete(0, END) for row in list_to_add: self.listbox.insert(END, str(row)) def grid(self, *args, **kwargs): return self.widget.grid(*args, **kwargs, sticky=E + W + N + S)
class ShapesMenu(object): """ """ def __init__(self, master, line_collection): try: self.width_of_entry = len(line_collection[0]) except IndexError: self.width_of_entry = 0 self.top = Toplevel(master) self.current_lines_listbox = Listbox(self.top) self.removed_lines_listbox = Listbox(self.top) self.submit = Button(self.top, text = "Ok", command=self.submit) self.remove_button = Button(self.top, text = "Remove", command=self.remove_line) self.cancel = Button(self.top, text = "Cancel", command=self.top.destroy) self.top.bind("<Return>", func=self.submit) self.current_lines = line_collection self.removed_lines = [] self.ids_internal = [] self.ids = [] for index, line in enumerate(self.current_lines): #removes the point data and converts the rest to strings id = line[1] if id not in self.ids_internal: self.ids_internal.append(id) self.ids.append(id) line = [str(element) for element in line[1:]] #put into the list self.current_lines_listbox.insert(index, " ".join(line)) self.current_lines_listbox.grid(row=0, column=0, columnspan=3) self.submit.grid(row=1, column=1) self.cancel.grid(row=1, column=2) self.remove_button.grid(row=1, column=0) def submit(self): #expose the internal IDs to remove to the exterior methods self.ids = self.ids_internal self.top.destroy() def remove_line(self): """Take the active line and remove it""" line_to_remove = self.current_lines_listbox.get(ANCHOR) id_to_remove = int(line_to_remove.split(" ")[0]) #remove it from the ID list self.ids_internal.remove(id_to_remove) #remove it from the listbox self.current_lines_listbox = self.current_lines_listbox.delete(ANCHOR)
class ChatGUI(Frame): def __init__(self, parent, conn): #Frame.__init__(self, parent, background="grey") self.parent = parent self.conn = conn self.centerWindow() self.initUI() def initUI(self): self.lineCounter = 0 # create a custom font self.customFontHeader = font.Font(family="Calibri", slant = "italic") #family="Helvetica", weight="bold", slant="italic") self.customFontMessage = font.Font(family="Calibri") self.parent.title("Python Chat") frame = Frame(self.parent) frame.pack(fill=BOTH, expand=1, side=LEFT) self.box = ScrolledText(frame, wrap=WORD, relief = GROOVE, width=30, height=18, font=self.customFontMessage) self.box.insert(END, 'Welcome to Python Chat!') self.box.config(state=DISABLED) self.box.pack(expand="yes", fill=BOTH, side=TOP) self.textarea = Text(frame, width=30, height=5) #self.textarea.insert(END, "") self.textarea.bind("<KeyRelease-Return>", self.gettext) #Se metto on press, rimane una newline in piu self.textarea.pack(expand="yes", fill=BOTH, side=TOP) okButton = Button(frame, text="Panic Button", activebackground="red", command=self.sendFile) okButton.pack(expand="no", fill=BOTH, side=TOP) self.usersFrame = Frame(self.parent) self.usersFrame.pack(fill=BOTH, expand=1, side=RIGHT) self.userListbox = Listbox(self.usersFrame, width=3) self.userListbox.pack(fill=BOTH, expand=1) self.updateUsersFrame() def centerWindow(self): w = 600 h = 475 sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() x = (sw - w)/2 y = (sh - h)/2 self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y)) def gettext(self, e): #e sta per event, questo e' un listener text = self.textarea.get("1.0", END) # 1.0: row:columa - END-2c rimuove l'ultimo carattere, una newline \r\n if "\n" in text: text = text.replace("\n", "") self.textarea.delete("0.0", END) #NON VA: il problema e' che viene inviato il carattere di newline ma non incluso nell'area a causa della bind mi sa. Devo escluderlo io self.sendToServer(text) def printConversation(self, message): self.box.config(state=NORMAL) self.box.insert(END,"\n" + message) self.lineCounter = self.lineCounter + 2 #m = re.match("\[.*\] From .*\n", self.box.get("0.0", END)) m = re.search("\[.*\].*:", message, re.MULTILINE) if m is not None: #print("MATCH") #print(m.group(0)) #print(str(m.start(0)) + "_" + str(m.end(0))) #print("COUNTER") #print(str(self.lineCounter) + "." + str(m.start(0)+1) + "___" + str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_add("header", str(self.lineCounter) + "." + str(m.start(0)), str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_config("header", font=self.customFontHeader, foreground = "blue") self.box.config(state=DISABLED) #self.box.yview_scroll(10000,"units") self.box.see(END) def sendToServer(self, messageToSend): self.conn.send(messageToSend.encode(encoding='utf_8', errors='strict')) def sendFile(self): #aprire una dialog di quelle predefinite (Sfoglia...) #capire come fare la send di un file sul socket... pass def updateUsersFrame(self): global connectedClients self.userListbox.delete(0, END) self.userListbox.insert(END, "Connected users") for item in connectedClients: self.userListbox.insert(END, item)
class ProblemBrowser(object): def __init__(self): self.action = None self.root = root = Tk() root.title('Never gonna fold you up') root.protocol("WM_DELETE_WINDOW", self.close) root.pack_propagate(True) scrollbar = Scrollbar(root, orient=tkinter.VERTICAL) self.problem_list = Listbox(root, exportselection=False, yscrollcommand=scrollbar.set) self.problem_list.pack(expand=True, fill=tkinter.BOTH, side=tkinter.LEFT) scrollbar.config(command=self.problem_list.yview) scrollbar.pack(side=tkinter.LEFT, fill=tkinter.Y) self.problem_list.bind('<<ListboxSelect>>', lambda evt: self.populate_problem_canvas()) self.problem_canvas = Canvas(root, bd=1, relief=tkinter.SUNKEN, width=500, height=500) self.problem_canvas.pack(expand=True, fill=tkinter.BOTH, side=tkinter.LEFT) self.problem_canvas.bind("<Configure>", lambda evt: self.populate_problem_canvas()) button_frame = Frame(root) button_frame.pack(fill=tkinter.Y, side=tkinter.LEFT) # Reposition the figure so it's center of mass is at 0.5, 0.5 v = IntVar() self.center_cb = Checkbutton(button_frame, text="center", variable=v, command=lambda: self.populate_problem_canvas()) self.center_cb.var = v self.center_cb.pack(side=tkinter.TOP) # Use meshes.reconstruct_facets instead of polygon/hole logic. v = IntVar() self.reconstruct_cb = Checkbutton(button_frame, text="reconstruct", variable=v, command=lambda: self.populate_problem_canvas()) self.reconstruct_cb.var = v self.reconstruct_cb.pack(side=tkinter.TOP) self.populate_problems() self.current_problem_name = None self.current_problem = None def populate_problems(self): self.problem_list.delete(0, tkinter.END) for file in sorted((get_root() / 'problems').iterdir()): self.problem_list.insert(tkinter.END, file.stem) def populate_problem_canvas(self): sel = self.problem_list.curselection() if not sel: return assert len(sel) == 1 name = self.problem_list.get(sel[0]) if name != self.current_problem_name: self.current_problem_name = name self.current_problem = load_problem(name) if self.current_problem: p = self.current_problem if self.center_cb.var.get(): p = center_problem(p) if self.reconstruct_cb.var.get(): facets = meshes.reconstruct_facets(p) facets = meshes.keep_real_facets(facets, p) skeleton = [e for f in facets for e in edges_of_a_facet(f)] p = Problem(facets, skeleton) draw_problem(self.problem_canvas, p) def run(self): self.root.mainloop() def close(self): if self.root: self.root.destroy() self.root = None
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent, background="#8080FF") self.parent = parent self.initUI() def initUI(self): self.parent.title("EQ GuildViewer 0.1") fontb = Font(size=12, weight="bold") # inicializo variables self.ant = None self.lastLine = 0 self.name = "" # frame padre area = Frame(self) area.pack(side=BOTTOM, fill=BOTH, expand=1) areab = Frame(self) areab.pack(side=TOP, fill=BOTH, expand=1) # scroll players self.scrollbar2 = Scrollbar(areab, orient=VERTICAL) # construimos un menu con todos los nombres del diccionario y un boton self.refreshButton = Button(areab, text="""PARSEA!""", command=self.onRefresh, bd=2, relief="groove") self.listboxLogs = Listbox( areab, width=50, activestyle="none", highlightthickness=0, yscrollcommand=self.scrollbar2.set, relief=RIDGE ) self.listboxLogs.pack(side=LEFT, fill=Y) self.scrollbar2.pack(side=LEFT, fill=Y) self.refreshButton.pack(side=LEFT, fill=BOTH, expand=1) for player in optionsDictionary: self.listboxLogs.insert(END, player) # scroll self.scrollbar = Scrollbar(area, orient=VERTICAL) self.scrollbar.pack(side=RIGHT, fill=Y) # area1 area1 = Frame(area) area1.pack(side=LEFT, fill=Y) lbl = Label(area1, text="Name") self.listbox = Listbox( area1, yscrollcommand=self.scrollbar.set, font=fontb, relief=FLAT, highlightthickness=0, activestyle="none" ) lbl.pack(side=TOP) self.listbox.pack(side=BOTTOM, fill=Y, expand=1) # area2 area2 = Frame(area) area2.pack(side=LEFT, fill=Y) lbl2 = Label(area2, text="Level") self.listbox2 = Listbox( area2, yscrollcommand=self.scrollbar.set, font=fontb, relief=FLAT, highlightthickness=0, activestyle="none" ) lbl2.pack(side=TOP) self.listbox2.pack(side=BOTTOM, fill=Y, expand=1) # area3 area3 = Frame(area) area3.pack(side=LEFT, fill=Y) lbl3 = Label(area3, text="Class") self.listbox3 = Listbox( area3, yscrollcommand=self.scrollbar.set, font=fontb, relief=FLAT, highlightthickness=0, activestyle="none" ) lbl3.pack(side=TOP) self.listbox3.pack(side=BOTTOM, fill=Y, expand=1) # area4 area4 = Frame(area) area4.pack(side=LEFT, fill=Y) lbl4 = Label(area4, text="Race") self.listbox4 = Listbox( area4, yscrollcommand=self.scrollbar.set, font=fontb, relief=FLAT, highlightthickness=0, activestyle="none" ) lbl4.pack(side=TOP) self.listbox4.pack(side=BOTTOM, fill=Y, expand=1) # area3 area5 = Frame(area) area5.pack(side=LEFT, fill=Y) lbl5 = Label(area5, text="Zone") self.listbox5 = Listbox( area5, yscrollcommand=self.scrollbar.set, font=fontb, relief=FLAT, highlightthickness=0, activestyle="none" ) lbl5.pack(side=TOP) self.listbox5.pack(side=BOTTOM, fill=Y, expand=1) self.pack(fill=BOTH, expand=1) # config-scrollbar self.scrollbar.config(command=self.yview) self.scrollbar2["command"] = self.listboxLogs.yview # bindeos de acciones self.listbox.bind("<<ListboxSelect>>", self.onSelect) self.listbox.bind("<MouseWheel>", self.onTest) self.listbox2.bind("<<ListboxSelect>>", self.onSelect) self.listbox2.bind("<MouseWheel>", self.onTest) self.listbox3.bind("<<ListboxSelect>>", self.onSelect) self.listbox3.bind("<MouseWheel>", self.onTest) self.listbox4.bind("<<ListboxSelect>>", self.onSelect) self.listbox4.bind("<MouseWheel>", self.onTest) self.listbox5.bind("<<ListboxSelect>>", self.onSelect) self.listbox5.bind("<MouseWheel>", self.onTest) self.listboxLogs.bind("<<ListboxSelect>>", self.onSelectPlayer) # mostrar la barra de scroll def yview(self, *args): self.listbox.yview(*args) self.listbox2.yview(*args) self.listbox3.yview(*args) self.listbox4.yview(*args) self.listbox5.yview(*args) # accion de la rueda del raton def onTest(self, val): return "break" # seleccionar un elementos de una listbox def onSelect(self, val): try: if self.ant != None: self.listbox.itemconfig(self.ant, background="#FFFFFF") self.listbox2.itemconfig(self.ant, background="#FFFFFF") self.listbox3.itemconfig(self.ant, background="#FFFFFF") self.listbox4.itemconfig(self.ant, background="#FFFFFF") self.listbox5.itemconfig(self.ant, background="#FFFFFF") self.listbox.itemconfig(val.widget.curselection(), background="#C0C0C0") self.listbox2.itemconfig(val.widget.curselection(), background="#C0C0C0") self.listbox3.itemconfig(val.widget.curselection(), background="#C0C0C0") self.listbox4.itemconfig(val.widget.curselection(), background="#C0C0C0") self.listbox5.itemconfig(val.widget.curselection(), background="#C0C0C0") self.ant = val.widget.curselection() except: None # print('No hay valores') # dependiendo de que nombre se elija en el menu cargamos en lastLine la linea de ese nombre del diccionario def onSelectPlayer(self, val): try: self.name = val.widget.get(val.widget.curselection()) self.lastLine = optionsDictionary[self.name] # print(self.name, ' ', self.lastLine) except: None # print('No hay valores') # recorremos el fichero log al clickar sobre el boton 'Refresh!' def onRefresh(self): if self.name != "": yes = False count = 0 dictionary = {} dictionaryAuxiliar = {} stringLog = "../eqlog_" + str(self.name) + "_project1999.txt" with open(stringLog, "r") as log: for i in range(int(self.lastLine)): next(log) count = count + 1 for line in log: match = re.match("\[.*\] \[(.*) (.*)\] (.*) \((.*)\) <.*> ZONE: (.*)", line) matchRole = re.match("\[.*\] \[(.*)\] (.*) <.*>", line) matchToken = re.match("\[.*\] You say, 't0000'", line) matchTokenI = re.match("\[.*\] You say, 't0001'", line) if matchTokenI != None: yes = True elif match != None and yes: dictionaryAuxiliar[match.group(3)] = ( match.group(1), match.group(2), match.group(4), match.group(5), ) elif matchRole != None and yes: dictionaryAuxiliar[matchRole.group(2)] = [(matchRole.group(1))] elif matchToken != None and yes: dictionary = dictionaryAuxiliar.copy() dictionaryAuxiliar.clear() yes = False count = count + 1 # bucle para sacar datos, primero eliminamos todo lo que haya self.listbox.delete(0, self.listbox.size()) self.listbox2.delete(0, self.listbox2.size()) self.listbox3.delete(0, self.listbox3.size()) self.listbox4.delete(0, self.listbox4.size()) self.listbox5.delete(0, self.listbox5.size()) for member in dictionary: self.listbox.insert(END, member) self.listbox2.insert(END, dictionary[member][0]) try: self.listbox3.insert(END, dictionary[member][1]) self.listbox4.insert(END, dictionary[member][2]) self.listbox5.insert(END, dictionary[member][3]) except IndexError as error: self.listbox3.insert(END, "-") self.listbox5.insert(END, "-") self.listbox4.insert(END, "-") # print(dictionary) # print('Longitud', len(dictionary)) # guardamos la linea ultima leida en el diccionario # self.lastLine = count # optionsDictionary[self.name] = count # print('Despues:', optionsDictionary) # guardamos el diccionario en el archivo options options = open("options.txt", "w") for player in optionsDictionary: options.write(str(player) + ":" + str(optionsDictionary[player])) options.close()
class LucteriosMainForm(Tk): def __init__(self): Tk.__init__(self) try: img = Image("photo", file=join( dirname(import_module('lucterios.install').__file__), "lucterios.png")) self.tk.call('wm', 'iconphoto', self._w, img) except: pass self.has_checked = False self.title(ugettext("Lucterios installer")) self.minsize(475, 260) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.running_instance = {} self.resizable(True, True) self.protocol("WM_DELETE_WINDOW", self.on_closing) self.ntbk = ttk.Notebook(self) self.ntbk.grid(row=0, column=0, columnspan=1, sticky=(N, S, E, W)) self.create_instance_panel() self.create_module_panel() stl = ttk.Style() stl.theme_use("default") stl.configure("TProgressbar", thickness=5) self.progress = ttk.Progressbar( self, style="TProgressbar", orient='horizontal', mode='indeterminate') self.progress.grid(row=1, column=0, sticky=(E, W)) self.btnframe = Frame(self, bd=1) self.btnframe.grid(row=2, column=0, columnspan=1) Button(self.btnframe, text=ugettext("Refresh"), width=20, command=self.refresh).grid( row=0, column=0, padx=3, pady=3, sticky=(N, S)) self.btnupgrade = Button( self.btnframe, text=ugettext("Search upgrade"), width=20, command=self.upgrade) self.btnupgrade.config(state=DISABLED) self.btnupgrade.grid(row=0, column=1, padx=3, pady=3, sticky=(N, S)) Button(self.btnframe, text=ugettext("Close"), width=20, command=self.on_closing).grid( row=0, column=2, padx=3, pady=3, sticky=(N, S)) def on_closing(self): all_stop = True instance_names = list(self.running_instance.keys()) for old_item in instance_names: if (self.running_instance[old_item] is not None) and self.running_instance[old_item].is_running(): all_stop = False if all_stop or askokcancel(None, ugettext("An instance is always running.\nDo you want to close?")): self.destroy() else: self.refresh() def destroy(self): instance_names = list(self.running_instance.keys()) for old_item in instance_names: if self.running_instance[old_item] is not None: self.running_instance[old_item].stop() del self.running_instance[old_item] Tk.destroy(self) def create_instance_panel(self): frm_inst = Frame(self.ntbk) frm_inst.grid_columnconfigure(0, weight=1) frm_inst.grid_rowconfigure(0, weight=1) frm_inst.grid_columnconfigure(1, weight=3) frm_inst.grid_rowconfigure(1, weight=0) self.instance_list = Listbox(frm_inst, width=20) self.instance_list.bind('<<ListboxSelect>>', self.select_instance) self.instance_list.pack() self.instance_list.grid(row=0, column=0, sticky=(N, S, W, E)) self.instance_txt = Text(frm_inst, width=75) self.instance_txt.grid(row=0, column=1, rowspan=2, sticky=(N, S, W, E)) self.instance_txt.config(state=DISABLED) self.btninstframe = Frame(frm_inst, bd=1) self.btninstframe.grid(row=1, column=0, columnspan=1) self.btninstframe.grid_columnconfigure(0, weight=1) Button(self.btninstframe, text=ugettext("Launch"), width=25, command=self.open_inst).grid( row=0, column=0, columnspan=2, sticky=(N, S)) Button(self.btninstframe, text=ugettext("Modify"), width=10, command=self.modify_inst).grid(row=1, column=0, sticky=(N, S)) Button(self.btninstframe, text=ugettext("Delete"), width=10, command=self.delete_inst).grid(row=1, column=1, sticky=(N, S)) Button(self.btninstframe, text=ugettext("Save"), width=10, command=self.save_inst).grid(row=2, column=0, sticky=(N, S)) Button(self.btninstframe, text=ugettext("Restore"), width=10, command=self.restore_inst).grid(row=2, column=1, sticky=(N, S)) Button(self.btninstframe, text=ugettext("Add"), width=25, command=self.add_inst).grid( row=3, column=0, columnspan=2, sticky=(N, S)) self.ntbk.add(frm_inst, text=ugettext('Instances')) def create_module_panel(self): frm_mod = Frame(self.ntbk) frm_mod.grid_columnconfigure(0, weight=1) frm_mod.grid_rowconfigure(0, weight=1) self.module_txt = Text(frm_mod) self.module_txt.grid(row=0, column=0, sticky=(N, S, W, E)) self.module_txt.config(state=DISABLED) self.ntbk.add(frm_mod, text=ugettext('Modules')) def do_progress(self, progressing): if not progressing: self.progress.stop() self.progress.grid_remove() else: self.progress.start(25) self.progress.grid(row=1, column=0, sticky=(E, W)) def enabled(self, is_enabled, widget=None): if widget is None: widget = self self.do_progress(not is_enabled) if is_enabled: widget.config(cursor="") else: widget.config(cursor="watch") if isinstance(widget, Button) and (widget != self.btnupgrade): if is_enabled and (not hasattr(widget, 'disabled') or not widget.disabled): widget.config(state=NORMAL) else: widget.config(state=DISABLED) else: for child_cmp in widget.winfo_children(): self.enabled(is_enabled, child_cmp) @ThreadRun def refresh(self, instance_name=None): if instance_name is None: instance_name = self.get_selected_instance_name() self.instance_txt.delete("1.0", END) self._refresh_instance_list() self.set_select_instance_name(instance_name) if not self.has_checked: self._refresh_modules() if self.instance_list.size() == 0: sleep(.3) self._refresh_modules() sleep(.3) self.after_idle(self.add_inst) def _refresh_modules(self): self.btnupgrade.config(state=DISABLED) self.module_txt.config(state=NORMAL) self.module_txt.delete("1.0", END) lct_glob = LucteriosGlobal() mod_lucterios, mod_applis, mod_modules = lct_glob.installed() self.module_txt.insert( END, ugettext("Lucterios core\t\t%s\n") % mod_lucterios[1]) self.module_txt.insert(END, '\n') self.module_txt.insert(END, ugettext("Application\n")) for appli_item in mod_applis: self.module_txt.insert( END, "\t%s\t%s\n" % (appli_item[0].ljust(30), appli_item[1])) self.module_txt.insert(END, ugettext("Modules\n")) for module_item in mod_modules: self.module_txt.insert( END, "\t%s\t%s\n" % (module_item[0].ljust(30), module_item[1])) extra_urls = lct_glob.get_extra_urls() if len(extra_urls) > 0: self.module_txt.insert(END, "\n") self.module_txt.insert(END, ugettext("Pypi servers\n")) for extra_url in extra_urls: self.module_txt.insert(END, "\t%s\n" % extra_url) self.module_txt.config(state=DISABLED) self.has_checked = True self.after(1000, lambda: Thread(target=self.check).start()) def _refresh_instance_list(self): self.instance_list.delete(0, END) luct_glo = LucteriosGlobal() instance_list = luct_glo.listing() for item in instance_list: self.instance_list.insert(END, item) if item not in self.running_instance.keys(): self.running_instance[item] = None instance_names = list(self.running_instance.keys()) for old_item in instance_names: if old_item not in instance_list: if self.running_instance[old_item] is not None: self.running_instance[old_item].stop() del self.running_instance[old_item] def set_select_instance_name(self, instance_name): cur_sel = 0 for sel_iter in range(self.instance_list.size()): if self.instance_list.get(sel_iter) == instance_name: cur_sel = sel_iter break self.instance_list.selection_set(cur_sel) self.select_instance(None) def get_selected_instance_name(self): if len(self.instance_list.curselection()) > 0: return self.instance_list.get(int(self.instance_list.curselection()[0])) else: return "" def set_ugrade_state(self, must_upgrade): if must_upgrade: self.btnupgrade.config(state=NORMAL) self.btnupgrade["text"] = ugettext("Upgrade needs") else: self.btnupgrade["text"] = ugettext("No upgrade") self.btnupgrade.config(state=DISABLED) def check(self): must_upgrade = False try: lct_glob = LucteriosGlobal() _, must_upgrade = lct_glob.check() finally: self.after(300, self.set_ugrade_state, must_upgrade) @ThreadRun def upgrade(self): self.btnupgrade.config(state=DISABLED) self.instance_list.config(state=DISABLED) try: from logging import getLogger admin_path = import_module( "lucterios.install.lucterios_admin").__file__ proc = Popen( [sys.executable, admin_path, "update"], stderr=STDOUT, stdout=PIPE) value = proc.communicate()[0] try: value = value.decode('ascii') except: pass six.print_(value) if proc.returncode != 0: getLogger("lucterios.admin").error(value) else: getLogger("lucterios.admin").info(value) showinfo(ugettext("Lucterios installer"), ugettext( "The application must restart")) python = sys.executable os.execl(python, python, *sys.argv) finally: self._refresh_modules() self.btnupgrade.config(state=NORMAL) self.instance_list.config(state=NORMAL) @ThreadRun def select_instance(self, evt): if self.instance_list['state'] == NORMAL: self.instance_list.config(state=DISABLED) try: instance_name = self.get_selected_instance_name() self.instance_txt.configure(state=NORMAL) self.instance_txt.delete("1.0", END) if instance_name != '': if instance_name not in self.running_instance.keys(): self.running_instance[instance_name] = None inst = LucteriosInstance(instance_name) inst.read() self.instance_txt.insert(END, "\t\t\t%s\n\n" % inst.name) self.instance_txt.insert( END, ugettext("Database\t\t%s\n") % inst.get_database_txt()) self.instance_txt.insert( END, ugettext("Appli\t\t%s\n") % inst.get_appli_txt()) self.instance_txt.insert( END, ugettext("Modules\t\t%s\n") % inst.get_module_txt()) self.instance_txt.insert( END, ugettext("Extra\t\t%s\n") % inst.get_extra_txt()) self.instance_txt.insert(END, '\n') if self.running_instance[instance_name] is not None and self.running_instance[instance_name].is_running(): self.instance_txt.insert(END, ugettext( "=> Running in http://%(ip)s:%(port)d\n") % {'ip': self.running_instance[instance_name].lan_ip, 'port': self.running_instance[instance_name].port}) self.btninstframe.winfo_children()[0]["text"] = ugettext( "Stop") else: self.running_instance[instance_name] = None self.instance_txt.insert(END, ugettext("=> Stopped\n")) self.btninstframe.winfo_children()[0]["text"] = ugettext( "Launch") else: self.btninstframe.winfo_children()[0]["text"] = ugettext( "Launch") self.btninstframe.winfo_children()[0].disabled = ( instance_name == '') self.btninstframe.winfo_children()[1].disabled = ( instance_name == '') self.btninstframe.winfo_children()[2].disabled = ( instance_name == '') self.btninstframe.winfo_children()[3].disabled = ( instance_name == '') self.btninstframe.winfo_children()[4].disabled = ( instance_name == '') self.instance_txt.configure(state=DISABLED) finally: setup_from_none() self.instance_list.config(state=NORMAL) @ThreadRun def add_modif_inst_result(self, result, to_create): inst = LucteriosInstance(result[0]) inst.set_extra("LANGUAGE_CODE='%s'" % result[5]) inst.set_appli(result[1]) inst.set_module(result[2]) inst.set_database(result[4]) if to_create: inst.add() else: inst.modif() inst = LucteriosInstance(result[0]) inst.set_extra(result[3]) inst.security() self.refresh(result[0]) def add_inst(self): self.enabled(False) try: self.do_progress(False) ist_edt = InstanceEditor() ist_edt.execute() ist_edt.transient(self) self.wait_window(ist_edt) finally: self.enabled(True) if ist_edt.result is not None: self.add_modif_inst_result(ist_edt.result, True) def modify_inst(self): self.enabled(False) try: self.do_progress(False) ist_edt = InstanceEditor() ist_edt.execute(self.get_selected_instance_name()) ist_edt.transient(self) self.wait_window(ist_edt) finally: self.enabled(True) if ist_edt.result is not None: self.add_modif_inst_result(ist_edt.result, False) @ThreadRun def delete_inst_name(self, instance_name): inst = LucteriosInstance(instance_name) inst.delete() self.refresh() def delete_inst(self): setup_from_none() instance_name = self.get_selected_instance_name() if askokcancel(None, ugettext("Do you want to delete '%s'?") % instance_name): self.delete_inst_name(instance_name) else: self.refresh() @ThreadRun def open_inst(self): instance_name = self.get_selected_instance_name() if instance_name != '': try: if instance_name not in self.running_instance.keys(): self.running_instance[instance_name] = None if self.running_instance[instance_name] is None: port = FIRST_HTTP_PORT for inst_obj in self.running_instance.values(): if (inst_obj is not None) and (inst_obj.port >= port): port = inst_obj.port + 1 self.running_instance[instance_name] = RunServer( instance_name, port) self.running_instance[instance_name].start() else: self.running_instance[instance_name].stop() self.running_instance[instance_name] = None finally: self.set_select_instance_name(instance_name) @ThreadRun def save_instance(self, instance_name, file_name): inst = LucteriosInstance(instance_name) inst.filename = file_name if inst.archive(): showinfo(ugettext("Lucterios installer"), ugettext( "Instance saved to %s") % file_name) else: showerror( ugettext("Lucterios installer"), ugettext("Instance not saved!")) self.refresh(instance_name) def save_inst(self): instance_name = self.get_selected_instance_name() if instance_name != '': file_name = asksaveasfilename( parent=self, filetypes=[('lbk', '.lbk'), ('*', '.*')]) if file_name != '': self.save_instance(instance_name, file_name) @ThreadRun def restore_instance(self, instance_name, file_name): if file_name[-4:] == '.bkf': rest_inst = MigrateFromV1(instance_name, withlog=True) else: rest_inst = LucteriosInstance(instance_name) rest_inst.filename = file_name if rest_inst.restore(): showinfo(ugettext("Lucterios installer"), ugettext( "Instance restore from %s") % file_name) else: showerror( ugettext("Lucterios installer"), ugettext("Instance not restored!")) self.refresh(instance_name) def restore_inst(self): instance_name = self.get_selected_instance_name() if instance_name != '': file_name = askopenfilename( parent=self, filetypes=[('lbk', '.lbk'), ('bkf', '.bkf'), ('*', '.*')]) if file_name != '': self.restore_instance(instance_name, file_name) def execute(self): self.refresh() center(self, (700, 300)) self.mainloop()
class BookManagerUi(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() self.db = dao('blist') #데이터베이스 관리 클래스 생성 def initUI(self): self.parent.title("Book Manager") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) self.columnconfigure(0, pad=3) self.columnconfigure(1, pad=3) self.columnconfigure(2, pad=3) self.rowconfigure(0, pad=3) self.rowconfigure(1, pad=3) self.rowconfigure(2, pad=3) self.rowconfigure(3, pad=3) self.rowconfigure(4, pad=3) self.rowconfigure(5, pad=3) self.rowconfigure(6, pad=3) self.input_bname='' self.input_aname='' self.input_price=0 self.delete='' lb_bookname = Label(self, text="bookname:") lb_bookname.grid(row=0, column =0 ,sticky=W, pady=4, padx=5) self.entry_bookname = Entry(self) self.entry_bookname.grid(row=0, column = 1 ) lb_author = Label(self, text="author:") lb_author.grid(row=0, column =2,sticky=W, pady=4, padx=5) self.entry_author = Entry(self) self.entry_author.grid(row=0, column = 3 ) lb_price = Label(self, text="price:") lb_price.grid(row=0, column =4 ,sticky=W, pady=4, padx=5) self.entry_price = Entry(self) self.entry_price.grid(row=0, column = 5 ,padx=15) abtn = Button(self, text="Add", command=lambda:self.clicked_add()) abtn.grid(row=0, column=6) sbtn = Button(self, text="Serach", command = lambda:self.clicked_search()) sbtn.grid(row=1, column=6, pady=4) dbtn = Button(self, text="Delete", command = lambda:self.clicked_delete()) dbtn.grid(row=2, column=6, pady=4) self.lb = Listbox(self) self.lb.grid(row=3,column = 0, columnspan = 6,rowspan= 4, sticky = E+W+S+N) self.lb.bind("<<ListboxSelect>>", self.onSelect) #삭제를 위한 select부분 def onSelect(self,val): sender = val.widget idx = sender.curselection() value = sender.get(idx) self.delete = value # 데이터 추가 버튼 def clicked_add(self): bname =self.entry_bookname.get() aname = self.entry_author.get() price = self.entry_price.get() self.lb.delete(0,END) # 입력받을 데이터가 모자란지 검사 if(len(bname) >0 and len(aname)>0 and len(price)>0 ): #가격에 문자를 입력했을 경우 처리 try: priceI = eval(price) except: self.lb.insert(END,"you input wrong price. it must be integer") #사용자가 입력한 내용중 중복된 책이름이 있을 경우(저자는 책이 여러가지일 수 있으니 제외) rec = self.db.excute_select(bname,'') if ( len(rec) >0): self.lb.insert(END,bname +" is already in the database") else: self.db.insert_data(bname,aname,priceI) # 모든 조건 만족시 데이터 입력 수행 r =self.db.excute_select(bname,aname) for rs in r: self.lb.insert(END,str(rs)) else: s = StringVar() self.entry_price.config(textvariable = s) self.lb.insert(END,"you have to input more values") #검색버튼 def clicked_search(self): bname =self.entry_bookname.get() aname = self.entry_author.get() self.lb.delete(0,END) #책이름 또는 저자이름 둘중 하나만입력 되어도 검색 가능하도록 if(len(bname)>0 or len(aname)>0 ): rec = self.db.excute_select(bname,aname) for r in rec: self.lb.insert(END,str(r)) else: self.lb.insert(END,"you have to input more values(bookname or author") #삭제 버튼 def clicked_delete(self): self.lb.delete(0,END) q = self.db.excute_delete(self.delete) self.lb.insert(END,q+' is delete from database')
class TextSelect(Frame): def __init__(self, client, anchor, items, destroyAnchor=False): """ Args: client: [SelectionClient] The window that text is returned to. anchor: A window that the text selection popup is created relative to. items: [str], items to display in the listbox. destroyAnchor: [bool] if true, destroy the anchor after positioning the window. """ self.top = Toplevel() self.anchor = anchor self.top.overrideredirect(1) self.top.wm_geometry('+%s+%s' % (anchor.winfo_rootx() + anchor.winfo_x(), anchor.winfo_rooty() + anchor.winfo_y() ) ) super(TextSelect, self).__init__(self.top) self.entry = Entry(self) self.client = client self.items = items self.place(x = 0.5, y = 0.5, height = 100, width = 100) self.entry.bind('<Return>', self.close) self.entry.bind('<KeyPress>', self.filter) self.entry.bind('<Escape>', self.abort) self.entry.bind('<Up>', self.up) self.entry.bind('<Down>', self.down) self.entry.pack() # Create the list of items. self.list = Listbox(self) for item in self.items: self.list.insert('end', item) self.list.pack() self.grid() self.entry.focus() # Reposition the select button against the anchor. We defer this # until after idle so that the anchor has a chance to get rendered. def reposition(*args): self.top.wm_geometry('+%s+%s' % ( anchor.winfo_rootx(), anchor.winfo_rooty()) ) if destroyAnchor: anchor.destroy() self.after_idle(reposition) def close(self, event): sel = self.list.curselection() if sel: item = self.list.get(sel[0]) else: item = self.entry.get() # Note that the order of this appears to be significant: destroying # before selecting leaves the focus in a weird state. self.client.selected(item) self.top.destroy() return 'braek' def abort(self, event): self.top.destroy() self.client.aborted() return 'break' def up(self, event): sel = self.list.curselection() if not sel: self.list.selection_set(0) return 'break' sel = sel[0] print('sel is %s size is %s' % (sel, self.list.size())) if sel > 0: print('setting selection to %s' % sel) self.list.selection_clear(sel) self.list.selection_set(sel - 1) self.list.see(sel) return 'break' def down(self, event): sel = self.list.curselection() if not sel: self.list.selection_set(0) return 'break' sel = sel[0] print('sel is %s size is %s' % (sel, self.list.size())) if sel < self.list.size() - 1: print('setting selection to %s' % (sel + 1)) self.list.selection_clear(sel) self.list.selection_set(sel + 1) self.list.see(sel) return 'break' def filter(self, event): """Filter the listbox based on the contents of the entryfield.""" # first add the character to the entry. currentText = self.entry.get() print(event.keysym) if event.keysym == 'BackSpace': # Handle backspace specially. if currentText: currentText = currentText[:-1] self.entry.delete(0, 'end') self.entry.insert(0, currentText) else: return 'break' else: # Assume normal character. Insert it. self.entry.insert('insert', event.char) currentText += event.char self.list.delete(0, 'end') pattern = currentText.upper() for item in self.items: if pattern in item.upper(): self.list.insert('end', item) return 'break'
class InstanceEditor(Toplevel): def __init__(self): Toplevel.__init__(self) self.focus_set() self.grab_set() self.result = None self.module_data = None self.mod_applis = None self.title(ugettext("Instance editor")) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.ntbk = ttk.Notebook(self) self.ntbk.grid(row=0, column=0, columnspan=1, sticky=(N, S, E, W)) self.frm_general = Frame(self.ntbk, width=350, height=150) self.frm_general.grid_columnconfigure(0, weight=0) self.frm_general.grid_columnconfigure(1, weight=1) self._general_tabs() self.ntbk.add(self.frm_general, text=ugettext('General')) self.frm_database = Frame(self.ntbk, width=350, height=150) self.frm_database.grid_columnconfigure(0, weight=0) self.frm_database.grid_columnconfigure(1, weight=1) self._database_tabs() self.ntbk.add(self.frm_database, text=ugettext('Database')) btnframe = Frame(self, bd=1) btnframe.grid(row=1, column=0, columnspan=1) Button(btnframe, text=ugettext("OK"), width=10, command=self.apply).grid( row=0, column=0, sticky=(N, S, E)) Button(btnframe, text=ugettext("Cancel"), width=10, command=self.destroy).grid( row=0, column=1, sticky=(N, S, W)) def _database_tabs(self): Label(self.frm_database, text=ugettext("Type")).grid( row=0, column=0, sticky=(N, W), padx=5, pady=3) self.typedb = ttk.Combobox( self.frm_database, textvariable=StringVar(), state=READLONY) self.typedb.bind("<<ComboboxSelected>>", self.typedb_selection) self.typedb.grid(row=0, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_database, text=ugettext("Name")).grid( row=1, column=0, sticky=(N, W), padx=5, pady=3) self.namedb = Entry(self.frm_database) self.namedb.grid(row=1, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_database, text=ugettext("User")).grid( row=2, column=0, sticky=(N, W), padx=5, pady=3) self.userdb = Entry(self.frm_database) self.userdb.grid(row=2, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_database, text=ugettext("Password")).grid( row=3, column=0, sticky=(N, W), padx=5, pady=3) self.pwddb = Entry(self.frm_database) self.pwddb.grid(row=3, column=1, sticky=(N, S, E, W), padx=5, pady=3) def _general_tabs(self): Label(self.frm_general, text=ugettext("Name")).grid( row=0, column=0, sticky=(N, W), padx=5, pady=3) self.name = Entry(self.frm_general) self.name.grid(row=0, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Appli")).grid( row=1, column=0, sticky=(N, W), padx=5, pady=3) self.applis = ttk.Combobox( self.frm_general, textvariable=StringVar(), state=READLONY) self.applis.bind("<<ComboboxSelected>>", self.appli_selection) self.applis.grid(row=1, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Modules")).grid( row=2, column=0, sticky=(N, W), padx=5, pady=3) self.modules = Listbox(self.frm_general, selectmode=EXTENDED) self.modules.configure(exportselection=False) self.modules.grid(row=2, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Language")).grid( row=3, column=0, sticky=(N, W), padx=5, pady=3) self.language = ttk.Combobox( self.frm_general, textvariable=StringVar(), state=READLONY) self.language.grid( row=3, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("CORE-connectmode") ).grid(row=4, column=0, sticky=(N, W), padx=5, pady=3) self.mode = ttk.Combobox( self.frm_general, textvariable=StringVar(), state=READLONY) self.mode.bind("<<ComboboxSelected>>", self.mode_selection) self.mode.grid(row=4, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Password")).grid( row=5, column=0, sticky=(N, W), padx=5, pady=3) self.password = Entry(self.frm_general, show="*") self.password.grid( row=5, column=1, sticky=(N, S, E, W), padx=5, pady=3) def typedb_selection(self, event): visible = list(self.typedb[VALUES]).index(self.typedb.get()) != 0 for child_cmp in self.frm_database.winfo_children()[2:]: if visible: child_cmp.config(state=NORMAL) else: child_cmp.config(state=DISABLED) def appli_selection(self, event): if self.applis.get() != '': appli_id = list(self.applis[VALUES]).index(self.applis.get()) luct_glo = LucteriosGlobal() current_inst_names = luct_glo.listing() appli_root_name = self.mod_applis[appli_id][0].split('.')[-1] default_name_idx = 1 while appli_root_name + six.text_type(default_name_idx) in current_inst_names: default_name_idx += 1 self.name.delete(0, END) self.name.insert( 0, appli_root_name + six.text_type(default_name_idx)) mod_depended = self.mod_applis[appli_id][2] self.modules.select_clear(0, self.modules.size()) for mod_idx in range(len(self.module_data)): current_mod = self.module_data[mod_idx] if current_mod in mod_depended: self.modules.selection_set(mod_idx) def mode_selection(self, event): visible = list(self.mode[VALUES]).index(self.mode.get()) != 2 for child_cmp in self.frm_general.winfo_children()[-2:]: if visible: child_cmp.config(state=NORMAL) else: child_cmp.config(state=DISABLED) def apply(self): from lucterios.framework.settings import DEFAULT_LANGUAGES, get_locale_lang if self.name.get() == '': showerror(ugettext("Instance editor"), ugettext("Name empty!")) return if self.applis.get() == '': showerror(ugettext("Instance editor"), ugettext("No application!")) return db_param = "%s:name=%s,user=%s,password=%s" % ( self.typedb.get(), self.namedb.get(), self.userdb.get(), self.pwddb.get()) security = "MODE=%s" % list( self.mode[VALUES]).index(self.mode.get()) if self.password.get() != '': security += ",PASSWORD=%s" % self.password.get() module_list = [ self.module_data[int(item)] for item in self.modules.curselection()] appli_id = list(self.applis[VALUES]).index(self.applis.get()) current_lang = get_locale_lang() for lang in DEFAULT_LANGUAGES: if lang[1] == self.language.get(): current_lang = lang[0] self.result = (self.name.get(), self.mod_applis[appli_id][ 0], ",".join(module_list), security, db_param, current_lang) self.destroy() def _load_current_data(self, instance_name): from lucterios.framework.settings import DEFAULT_LANGUAGES, get_locale_lang lct_inst = LucteriosInstance(instance_name) lct_inst.read() self.name.delete(0, END) self.name.insert(0, lct_inst.name) self.name.config(state=DISABLED) applis_id = 0 for appli_iter in range(len(self.mod_applis)): if self.mod_applis[appli_iter][0] == lct_inst.appli_name: applis_id = appli_iter break self.applis.current(applis_id) if lct_inst.extra['']['mode'] is not None: self.mode.current(lct_inst.extra['']['mode'][0]) else: self.mode.current(2) self.mode_selection(None) typedb_index = 0 for typedb_idx in range(len(self.typedb[VALUES])): if self.typedb[VALUES][typedb_idx].lower() == lct_inst.database[0].lower(): typedb_index = typedb_idx break self.typedb.current(typedb_index) self.typedb.config(state=DISABLED) self.typedb_selection(None) self.namedb.delete(0, END) if 'name' in lct_inst.database[1].keys(): self.namedb.insert(0, lct_inst.database[1]['name']) self.userdb.delete(0, END) if 'user' in lct_inst.database[1].keys(): self.userdb.insert(0, lct_inst.database[1]['user']) self.pwddb.delete(0, END) if 'password' in lct_inst.database[1].keys(): self.pwddb.insert(0, lct_inst.database[1]['password']) self.modules.select_clear(0, self.modules.size()) for mod_idx in range(len(self.module_data)): current_mod = self.module_data[mod_idx] if current_mod in lct_inst.modules: self.modules.select_set(mod_idx) current_lang = get_locale_lang() if 'LANGUAGE_CODE' in lct_inst.extra.keys(): current_lang = lct_inst.extra['LANGUAGE_CODE'] for lang in DEFAULT_LANGUAGES: if lang[0] == current_lang: self.language.current(self.language[VALUES].index(lang[1])) def execute(self, instance_name=None): from lucterios.framework.settings import DEFAULT_LANGUAGES, get_locale_lang self.mode[VALUES] = [ugettext( "CORE-connectmode.0"), ugettext("CORE-connectmode.1"), ugettext("CORE-connectmode.2")] self.language[VALUES] = [lang[1] for lang in DEFAULT_LANGUAGES] self.typedb[VALUES] = ["SQLite", "MySQL", "PostgreSQL"] lct_glob = LucteriosGlobal() _, self.mod_applis, mod_modules = lct_glob.installed() self.mod_applis.sort(key=lambda item: get_module_title(item[0])) self.modules.delete(0, END) self.module_data = [] module_list = [] for mod_module_item in mod_modules: module_list.append( (get_module_title(mod_module_item[0]), mod_module_item[0])) module_list.sort(key=lambda module: module[0]) for module_title, module_name in module_list: self.modules.insert(END, module_title) self.module_data.append(module_name) appli_list = [] for mod_appli_item in self.mod_applis: appli_list.append(get_module_title(mod_appli_item[0])) self.applis[VALUES] = appli_list if instance_name is not None: self._load_current_data(instance_name) else: self.typedb.current(0) self.mode.current(2) if len(appli_list) > 0: self.applis.current(0) self.appli_selection(None) self.mode_selection(None) self.typedb_selection(None) for lang in DEFAULT_LANGUAGES: if lang[0] == get_locale_lang(): self.language.current(self.language[VALUES].index(lang[1])) center(self)
class MemberChecker(PanedWindow): def __init__(self, parent): PanedWindow.__init__(self, parent, background="white") self.parent = parent self.init_data() self.init_log() self.init_ui() self.update_status() def init_data(self): self.data_store = api.DataStore() def init_log(self): self.entrance_log = entrance_log.EntranceLog() def init_ui(self): self.parent.title("Member Checker") self.columnconfigure(3, weight=3) self.pack(fill=BOTH, expand=True) self.input = StringVar() self.input_entry = Entry(self, textvariable=self.input) self.input_entry.bind('<Return>', self.submit) self.input_entry.grid(row=0, column=0, columnspan=3, sticky=E + W) self.result = StringVar() self.result_label = Label(self, textvariable=self.result) self.result_label.grid(row=3, column=0, columnspan=3, sticky=E + W) self.name = StringVar() name_label = Label(self, textvariable=self.name) name_label.grid(row=2, column=0, columnspan=3, sticky=E + W) self.status = StringVar() status_label = Label(self, textvariable=self.status) status_label.grid(row=4, column=0, columnspan=4, sticky=E + W) submit_button = Button(self, text="Submit", command=self.submit) submit_button.grid(row=1, column=2) enter_without_card_button = Button(self, text="Enter without card", command=self.enter_without_card) enter_without_card_button.grid(row=1, column=0) enter_member_without_card_button = Button(self, text="Enter member without card", command=self.enter_member_without_card) enter_member_without_card_button.grid(row=1, column=1) self.entrance_log_list = Listbox(self) self.entrance_log_list.grid(row=0, column=3, rowspan=4, sticky=E + W + S + N) self.input_entry.focus() def load_data(self): if messagebox.askyesno("Load new API Data", "Are you sure you want to load the new API data? All previous data will be removed. The program might be unresponsive for a few seconds, but don't kill it, please! It has feelings too."): self.data_store.load_api_data() def enter_by_identification(self, identification): member = self.data_store.find_member_by_identification(identification) if member is None: if messagebox.askyesno("Not a member", "This university identification is not registered as a member. Do you want to let them in as a non-member?"): self.enter_non_member_by_identification(identification) else: self.enter_member(member) def enter_by_barcode(self, barcode): member = self.data_store.find_member_by_barcode(barcode) if member is None: if messagebox.askyesno("Not a member", "This barcode is not registered as a member. Do you want to let them in as a non-member?"): self.enter_non_member_by_barcode(barcode) else: self.enter_member(member) def enter_non_member_by_identification(self, identification): self.entrance_log.enter_non_member_by_identification(identification) self.enter_non_member() def enter_non_member_by_barcode(self, barcode): self.entrance_log.enter_non_member_by_barcode(barcode) self.enter_non_member() def enter_without_card(self): self.clear_result() self.entrance_log.enter_without_card() self.enter_non_member() self.input_entry.focus() def enter_member(self, member): inside_result = self.entrance_log.is_member_inside(member) if inside_result[0]: if not messagebox.askyesno("Already inside", "This membership card has already been used to enter at {}. Are you sure you want to register it again? Normally you should let this person enter without card (and bill them accordingly).".format( inside_result[1])): return self.entrance_log.enter_member(member) self.result.set('Member!') self.result_label.configure(background='green') self.name.set(member['firstName'] + ' ' + member['lastName']) self.update_status() def enter_non_member(self): self.result.set('Not a member!') self.result_label.configure(background='red') self.name.set('Not in the database') self.update_status() def enter_member_without_card(self): name = self.input.get() if len(name) == 0: messagebox.showinfo('Name required', 'Please enter the name of this person!') return self.entrance_log.enter_member_without_card(name) self.result.set('Member without card!') self.result_label.configure(background="orange") self.name.set('') self.input.set('') self.update_status() def clear_result(self): self.result.set('') self.result_label.configure(background='white') self.name.set('') def submit(self, event=None): self.clear_result() entry = self.input.get() if helpers.is_valid_identification(entry): self.enter_by_identification(entry) elif helpers.is_valid_barcode(entry): self.enter_by_barcode(entry) else: messagebox.showinfo('Invalid entry', 'The data entered was not recognized as a valid bar code or a valid university identification. You should click \'enter without card\' to let this person in.') return self.input.set('') self.input_entry.focus() def clear_log(self): if messagebox.askyesno("Clear log", "Are you sure you want to clear the log of all people who entered?"): self.entrance_log.clear_log() self.update_status() def update_status(self): self.status.set("{} members inside. Total: {}".format(self.entrance_log.members_inside_count(), self.entrance_log.inside_count())) logs = self.entrance_log.get_latest_logs(15) self.entrance_log_list.delete(0, 15) for l in logs: s = l['timestamp'] + ": " data = l['data'] if 'member_id' in data: member = self.data_store.find_member(data['member_id']) s += member['firstName'] + " " + member['lastName'] elif 'barcode' in data: s += data['barcode'] elif 'identification' in data: s += data['identification'] elif 'name' in data: s += '[no card]' + data['name'] else: s += "-" self.entrance_log_list.insert(0, s)
class Masfir(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self._initUI() def _initUI(self): """ Initialise the UI """ self.parent.title("Masfir v0.1") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) self._createMenu() self._createUIElements() def _createMenu(self): """ Create the menu """ menubar = Menu(self.parent) self.parent.config(menu=menubar) # File Menu mnuFile = Menu(menubar) mnuFile.add_command(label="Exit", underline=1, command=self._onMenuFileExit) menubar.add_cascade(label="File", underline=0, menu=mnuFile) # Help Menu mnuHelp = Menu(menubar) mnuHelp.add_command(label="About", underline=0, command=self._onMenuHelpAbout) menubar.add_cascade(label="Help", underline=0, menu=mnuHelp) def _createUIElements(self): """ Create the main frame's UI elements """ # Top frame with the Load Directory controls frmLoadDir = Frame(self) frmLoadDir.pack(side=TOP, anchor=N, fill=X) self.sLoadDirVar = StringVar() lblLoadDir = Label(frmLoadDir, text="<Empty Directory>", textvariable=self.sLoadDirVar) lblLoadDir.pack(side=LEFT) btnLoadDir = Button(frmLoadDir, text="Load Directory", command=self._onBtnLoadDir) btnLoadDir.pack(side=RIGHT) # Dropdown with list of series (directories) detected frmSeriesSelector = Frame(self) frmSeriesSelector.pack(side=TOP, anchor=N, fill=X) self.sSeriesVar = StringVar() self.optSeries = OptionMenu(frmSeriesSelector, self.sSeriesVar, 'one', 'two', 'three', 'Loading', command=self._onBtnSeriesSelected) self.optSeries.pack(side=LEFT) # The two diff-style listboxes containing original and new episode list names frmListBoxes = Frame(self) frmListBoxes.pack(fill=BOTH, expand=1) self.lstOrgFiles = Listbox(frmListBoxes) self.lstOrgFiles.bind("<<ListboxSelect>>", self._onListOrgFiles) self.lstOrgFiles.pack(side=LEFT, fill=BOTH, expand=1, anchor=W) self.lstNewFiles = Listbox(frmListBoxes) self.lstNewFiles.bind("<<ListboxSelect>>", self._onListNewFiles) self.lstNewFiles.pack(side=RIGHT, fill=BOTH, expand=1, anchor=E) # Bottom buttons frmFinal = Frame(self) frmFinal.pack(side=BOTTOM, anchor=S, fill=X) btnRename = Button(frmFinal, text="Rename", command=self._onBtnRename) btnRename.pack(side=LEFT) btnExit = Button(frmFinal, text="Exit", command=self._onBtnExit) btnExit.pack(side=RIGHT) def _onBtnLoadDir(self): selectedDirectory = filedialog.askdirectory() self.optSeries['menu'].delete(0, END) # self.optSeries['menu'].insert('one', 'two', 'three') self.sSeriesVar.set('two') self.sLoadDirVar.set(selectedDirectory) # Populate listbox self.lstOrgFiles.delete(0, END) for item in os.listdir(selectedDirectory): self.lstOrgFiles.insert(END, item) def _onBtnExit(self): self._exit() def _onListOrgFiles(self): pass def _onListNewFiles(self): pass def _onBtnSeriesSelected(self): pass def _onBtnRename(self): pass def _onMenuFileExit(self): """ Jump to _exit() if Exit is clicked """ self._exit() def _onMenuHelpAbout(self): """ Something here """ pass def _exit(self): """ Exit the app """ self.quit()
class Application(): def __init__(self, master, network, debug=False): """ Init method for the Application class, this method is the GUI Class for our solution, it gets master (Tk root, network and debug (Open debug window if needded) :param master: The root Tk of the Application :param network: network is object from Network class (communication) :param debug: bool, to open or not.. """ self.init_constants(master, network) # create constants self.__create_top_toolbar() self.__create_app_frame() self.bindings() self.__network.listen() # network mainloop.. if debug: self.debug = True self.open_debug_dialog() def init_constants(self, master, network): """ This function contruct all the vital constant for this class it gets the root and the network and save them as constant of the class :param master: The root Tk of the Application :param network: network is object from Network class (communication) """ self.__master_splinter = master self.__user_color = StringVar() self.__current_shape = None self.__drawing_shape = None self.__users_list = [] self.__points = [] # private because I dont want that someone change them self.__network = network # private for the same reason self.debug = False def __create_app_frame(self): """ This function creates and pack (using grid) the main app frame (The left toolbar (users list) and the canvas """ app_frame = Frame(self.__master_splinter) self.create_game_canvas(app_frame) self.create_left_toolbar(app_frame) app_frame.grid(row=1) def create_game_canvas(self, app_frame): """ This function creates and pack the game canvas :param app_frame: Tk frame object """ self.canvas = Canvas(app_frame, width=500, height=500, bg='white') self.canvas.grid(column=1) def __create_top_toolbar(self): """ This function creates and pack the top toolbar (with all the colors, shapes and etc.. """ top_toolbar = Frame(self.__master_splinter) help_button = Button(top_toolbar, text="Help", command=self.open_help_dialog) help_button.grid(row=0, column=4) color_frame = self.create_color_frame(top_toolbar) color_frame.grid(row=0, column=0) empty_label = Label(top_toolbar, padx=20) empty_label.grid(column=1, row=0) my_shapes_frame = self.create_shape_buttons(top_toolbar) my_shapes_frame.grid(row=0, column=2) empty_label = Label(top_toolbar, padx=45) empty_label.grid(column=3, row=0) top_toolbar.grid(row=0) def create_left_toolbar(self, app_frame): """ This function creates and pack the left toolbar :param app_frame: root for this toolbar.. (Frame obj) :return: """ left_toolbar = Frame(app_frame) self.lb_users = Listbox(left_toolbar) self.lb_users.config(height=30) self.lb_users.grid(row=0, column=0) scroll_bar = Scrollbar(left_toolbar) scroll_bar.config(command=self.lb_users.yview) scroll_bar.grid(row=0, column=1, sticky='ns') left_toolbar.propagate("false") left_toolbar.grid(column=0, row=0) self.lb_users.config(yscrollcommand=scroll_bar.set) self.debug_event("Left toolbar was generated") def create_shape_buttons(self, root): """ This function get a root and creates all the shapes buttons (because they have picture they need to compile and resize the icons... :param root: Tk frame :return: returns Frame object (it won`t pack it) """ shapes_frame = Frame(root) shape_text = Label(shapes_frame, text="Shape: ") shape_text.grid(row=0, column=0) self.line_image = self.create_shape_img(SHAPES_DICT[LINE]) line_btn = Button(shapes_frame, image=self.line_image, command=lambda: self.create_shape(LINE)) line_btn.grid(row=0, column=1) self.square_image = self.create_shape_img(SHAPES_DICT[SQUARE]) square_btn = Button(shapes_frame, image=self.square_image, command=lambda: self.create_shape(SQUARE)) square_btn.grid(row=0, column=2) self.triangle_image = self.create_shape_img(SHAPES_DICT[TRIANGLE]) triangle_btn = Button(shapes_frame, image=self.triangle_image, command=lambda: self.create_shape(TRIANGLE)) triangle_btn.grid(row=0, column=3) self.elipse_image = self.create_shape_img(SHAPES_DICT[ELIPSE]) elipse_btn = Button(shapes_frame, image=self.elipse_image, command=lambda: self.create_shape(ELIPSE)) elipse_btn.grid(row=0, column=4) self.debug_event("shapes toolbar was generated") return shapes_frame def create_color_frame(self, root): """ This function creates a color frame :param root: Frame obj :return: frame.. """ color_frame = Frame(root) color_text = Label(color_frame, text="Color: ") color_text.grid(row=0, column=0) self.colors_list = ttk.Combobox(color_frame, textvariable=self.__user_color, values=COLOR_LIST, state="readonly") self.colors_list.grid(row=0, column=1) self.colors_list.current(FIRST_COLOR) self.debug_event("color toolbar was generated") return color_frame def create_shape_img(self, path): """ This function get a path for picture.. and creates a icon in size of 32X32 :param path: :return: """ img = Image.open(path) img = img.resize(ICON_SIZE, Image.ANTIALIAS) return ImageTk.PhotoImage(img) def bindings(self): """ This is our binding function.. it bind some things in the GUI some events like get new user, get clicks, close window """ self.canvas.bind(LEFT_BUTTON_CLICK, lambda event: self.try_draw_user_shape(event)) self.__master_splinter.bind(JOIN_EVT, lambda x: self.change_users_list(JOIN_EVT, self.__network.get_event(JOIN_EVT))) self.__master_splinter.bind(LEAVE_EVT, lambda x: self.change_users_list(LEAVE_EVT, self.__network.get_event(LEAVE_EVT))) self.__master_splinter.bind(SHAPE_EVT, lambda event: self.shape_handler()) self.__master_splinter.bind(USERS_EVT, lambda event: self.init_users()) self.__master_splinter.protocol(CLOSE_WINDOW_PROT, self.on_close) def create_shape(self, shape_type): """ After click on Shape this function appear :) it set the current shape to "shape type" :param shape_type: String repr shape type """ self.canvas.config(cursor="target") self.__points = [] self.__current_shape = shape_type self.debug_event("button " + shape_type + " clicked") def shape_handler(self): """ This function handle new shapes events :return: """ shape = self.__network.get_event(SHAPE_EVT) points = self.points_to_tuple(shape[COORDS]) self.debug_event("shape msg:") self.debug_event(str(points)) self.draw_shape(points, shape[SHAPE_TYPE], shape[USER], shape[COLOR]) def init_users(self): """ This function handle "connected" msg when connected it asks the communicator for users list, group name and user name and update the users list """ group_name = self.__network.get_group() self.add_user_to_list(group_name + ":") user = self.__network.get_user_name() self.add_user_to_list(user) users = self.__network.get_user_list() self.debug_event("users list generated") for user in users: self.add_user_to_list(user) def try_draw_user_shape(self, event): """ This function handles canvas clicks, after any click on the canvas this function checks if there was enough clicks to create the relevant shape (If shape is None it won`t happen..) :param event: event obj, contain the x,y of the click """ # trying to draw if self.__current_shape is not self.__drawing_shape: # check if it is a new shape self.__drawing_shape = self.__current_shape self.__points.append((event.x, event.y)) if len(self.__points) is POINTS_NEEDED[self.__drawing_shape]: # Success self.send_shape_details_and_restart() self.debug_event("button is clicked in " + str(event.x) + "," + str(event.y)) def send_shape_details_and_restart(self): """ This function called when the user completed a shape it send to communicator a message the says "New shape was added" """ self.__network.shape_msg([self.__drawing_shape, self.__points, self.__user_color.get()]) self.__current_shape = None self.__drawing_shape = None self.__points = [] self.canvas.config(cursor="") def draw_shape(self, points, s_type, user_name, color): """ This function draw a new shape on the screen :param points: "x,y,z,w,a,b" string that each odd nu is x and each even is y :param s_type: shape type, string :param user_name: user_name string :param color: color, string """ if s_type == LINE: self.canvas.create_line(points, fill=color, width=LINE_WIDTH) elif s_type == SQUARE: self.canvas.create_rectangle(points, fill=color) elif s_type == ELIPSE: self.canvas.create_oval(points, fill=color) elif s_type == TRIANGLE: self.canvas.create_polygon(points, fill=color) self.canvas.create_text(points[:FIRST_XY], text=user_name) self.debug_event("draws: " + s_type) def points_to_tuple(self, str_points): """ this function gets alot of numbers in string and returns :param str_points: "x,y,z,w,a,b" string that each odd nu is x and each even is y :return: list of coordinates as tuple in format (x,y,x,y,x,y) """ nums = str_points.split(',') return tuple(nums) def open_help_dialog(self): """ This function creates new "help" dialog :return: """ try: self.help_frame.destroy() except: pass infromative_txt = self.get_informative_text() self.help_frame = Tk() self.help_frame.title(HELP_TITLE) infromative_text = Label(self.help_frame, text=infromative_txt) infromative_text.pack() self.help_frame.mainloop() def get_informative_text(self): f = open(INFO_DIR, READ_PREM) reader = f.read() f.close() return reader def open_debug_dialog(self): """ this function create new "debug" dialog :return: """ self.debug_frame = Tk() self.debug_frame.title(DEBUG_TITLE) self.debug_messages = Text(self.debug_frame) self.debug_messages.insert(END, "Messages") self.debug_messages.pack() self.debug_frame.mainloop() def debug_event(self, event): """ This function check if the debug option is enabled if it is it will record the event in the debug messages dialog :param event: string repr event to debug.. """ if self.debug: self.debug_messages.insert(END, "\nEVENT: " + str(event)) def on_close(self): """ Handles closing the programe :return: """ self.__network.leave_msg() self.__master_splinter.destroy() try: self.debug_frame.destroy() self.help_frame.destroy() except: pass def change_users_list(self, msg_type, user): """ Handle "change user" event (Leave\Join) :param msg_type: CONSTANT, JOIN\LEAVE :param user: list of users.. """ users = user[ONE_USER] self.debug_event(user + " has " + msg_type) if msg_type is LEAVE_EVT: self.remove_user_from_list(users) elif msg_type is JOIN_EVT: self.add_user_to_list(users) def add_user_to_list(self, user): """ Add specific user the list_box.. of users list :param user: string repr username """ if user not in self.__users_list: self.__users_list.append(user) self.lb_users.insert(END, user) else: self.debug_event(user + " already exists") def remove_user_from_list(self, user): """ This function tries to delete specific username from the list :param user: string repr username :return: """ try: i = self.__users_list.index(user) self.lb_users.delete(i) self.__users_list.pop(i) except: self.debug_event(user + " is not in our list..")
class ListboxVidget(Vidget, Eventor): """ ListboxVidget contains a Listbox widget. It adds the following abilities: - Store items of any type, unlike Listbox widget that only stores texts. - Remember selected item even if the listbox widget lost focus. - Notify pre-change and post-change events. """ # Error raised when trying to change the listbox while a change is going on class CircularCallError(ValueError): pass # Error raised when trying to change the listbox while it is disabled class DisabledError(ValueError): pass # Event notified when the listbox's items are to be changed ITEMS_CHANGE_SOON = 'ITEMS_CHANGE_SOON' # Event notified when the listbox's items are changed ITEMS_CHANGE_DONE = 'ITEMS_CHANGE_DONE' # Event notified when the listbox's active item is to be changed ITEMCUR_CHANGE_SOON = 'ITEMCUR_CHANGE_SOON' # Event notified when the listbox's active item is changed ITEMCUR_CHANGE_DONE = 'ITEMCUR_CHANGE_DONE' # Events list EVENTS = ( ITEMS_CHANGE_SOON, ITEMS_CHANGE_DONE, ITEMCUR_CHANGE_SOON, ITEMCUR_CHANGE_DONE, ) def __init__( self, items=None, item_to_text=None, normal_bg='', normal_fg='', active_bg='sky blue', active_fg='white', selected_bg='steel blue', selected_fg='white', master=None, ): """ Initialize object. @param items: Items list. @param item_to_text: Item-to-text function. Default is `str`. @param normal_bg: Unselected item background color. @param normal_fg: Unselected item foreground color. @param active_bg: Active item background color. `Active` means the item is selected (in general meaning) but the listbox has no focus. @param active_fg: Active item foreground color. `Active` means the item is selected (in general meaning) but the listbox has no focus. @param selected_bg: Selected item background color. `Selected` means the item is selected (in general meaning) and the listbox has focus. @param selected_fg: Selected item foreground color. `Selected` means the item is selected (in general meaning) and the listbox has focus. @param master: Master widget. @return: None. """ # Initialize Vidget. # Create main frame widget. Vidget.__init__( self, master=master, ) # Initialize Eventor Eventor.__init__(self) # If items list is given if items is not None: # If items list is not list if not isinstance(items, list): # Raise error raise TypeError(items) # If items list is list. # If items list is not given, or items list is given and is list # Items list self._items = items if items is not None else [] # Item-to-text function. Default is `str`. self._item_to_text = item_to_text if item_to_text is not None else str # Unselected item background color self._normal_fg = normal_fg # Unselected item foreground color self._normal_bg = normal_bg # Active item background color self._active_fg = active_fg # Active item foreground color self._active_bg = active_bg # Selected item background color self._selected_fg = selected_fg # Selected item foreground color self._selected_bg = selected_bg # Whether the listbox is changing self._is_changing = False # Active index. `-1` means void, i.e. no item is active. self._indexcur = -1 # Whether active index is being reset to same value self._is_resetting = False # Create listbox widget self._listbox = Listbox( master=self.widget(), relief='groove', activestyle='none', highlightthickness=0, # Active index cache only supports single-selection mode for now. # See 2N6OR. selectmode='single', ) # Set the listbox widget as config target self.config_target_set(self._listbox) # Create x-axis scrollbar self._scrollbar_xview = _HiddenScrollbar( self.widget(), orient=HORIZONTAL, ) # Create y-axis scrollbar self._scrollbar_yview = _HiddenScrollbar( self.widget(), orient=VERTICAL, ) # Mount scrollbars self._listbox.config(xscrollcommand=self._scrollbar_xview.set) self._listbox.config(yscrollcommand=self._scrollbar_yview.set) self._scrollbar_xview.config(command=self._listbox.xview) self._scrollbar_yview.config(command=self._listbox.yview) # Bind single-click event handler self._listbox.bind('<Button-1>', self._on_single_click) # Bind double-click event handler self._listbox.bind('<Double-Button-1>', self._on_double_click) # Update listbox widget self._listbox_widget_update(keep_active=False) # Update widget self._widget_update() def _widget_update(self): """ Update widget. @return: None. """ # Row 0 for listbox and y-axis scrollbar self.widget().rowconfigure(0, weight=1) # Row 1 for x-axis scrollbar self.widget().rowconfigure(1, weight=0) # Column 0 for listbox and x-axis scrollbar self.widget().columnconfigure(0, weight=1) # Column 1 for y-axis scrollbar self.widget().columnconfigure(1, weight=0) # Lay out listbox self._listbox.grid(row=0, column=0, sticky='NSEW') # Lay out x-axis scrollbar self._scrollbar_xview.grid(row=1, column=0, sticky='EW') # Lay out y-axis scrollbar self._scrollbar_yview.grid(row=0, column=1, sticky='NS') def is_enabled(self): """ Test whether the listbox is enabled. @return: Boolean. """ # Return whether the listbox is enabled return self._listbox.config('state')[4] != DISABLED def is_changing(self): """ Test whether the listbox is changing. @return: Boolean. """ # Return whether the listbox is changing return self._is_changing def is_resetting(self): """ Test whether the listbox is setting active index to the same value. @return: Boolean. """ # Return whether the listbox is setting active index to the same value return self._is_resetting def size(self): """ Get number of items. @return: Number of items. """ # Return number of items return len(self._items) def items(self): """ Get items list. Notice do not change the list outside. @return: Items list. """ # Return items list return self._items def items_set( self, items, notify=True, keep_active=False, ): """ Set items list. Notice do not change the list outside. @param items: Items list. @param notify: Whether notify pre-change and post-change events. @param keep_active: Whether keep or clear active index. @return: None. """ # If the items is not list if not isinstance(items, list): # Raise error raise TypeError(items) # If the items is list. # If the listbox is disabled if not self.is_enabled(): # Raise error raise ListboxVidget.DisabledError() # If the listbox is not disabled. # If the listbox is changing if self._is_changing: # Raise error raise ListboxVidget.CircularCallError() # If the listbox is not changing. # Set changing flag on self._is_changing = True # If notify events if notify: # Notify pre-change event self.handler_notify(self.ITEMS_CHANGE_SOON) # Store the new items self._items = items # Update listbox widget self._listbox_widget_update( keep_active=keep_active ) # If notify events if notify: # Notify post-change event self.handler_notify(self.ITEMS_CHANGE_DONE) # Set changing flag off self._is_changing = False def index_is_valid(self, index): """ Test whether given index is valid. Notice -1 is not valid. @param index: Index to test. @return: Boolean. """ # Test whether given index is valid return 0 <= index and index < self.size() def index_is_valid_or_void(self, index): """ Test whether given index is valid or is -1. @param index: Index to test. @return: Boolean. """ # Test whether given index is valid or is -1 return index == -1 or self.index_is_valid(index) def index_first(self): """ Get the first item's index. @return: First item's index, or -1 if the listbox is empty. """ # Return the first item's index return 0 if self.size() > 0 else -1 def index_last(self): """ Get the last item's index. @return: Last item's index, or -1 if the listbox is empty. """ # Return the last item's index return self.size() - 1 def indexcur(self, internal=False, raise_error=False): """ Get the active index. @param internal: See 2N6OR. @return: The active index. If no active active, either return -1, or raise IndexError if `raise_error` is True. """ # Get active indexes indexcurs = self._indexcurs(internal=internal) # If have active indexes if indexcurs: # Return the first active index return indexcurs[0] # If no active indexes else: # If raise error if raise_error: # Raise error raise IndexError(-1) # If not raise error else: # Return -1 return -1 def _indexcurs(self, internal=False): """ Get active indexes list. 2N6OR @param internal: Whether use listbox widget's selected indexes, instead of cached active index. Notice listbox widget has no selected indexes if it has no focus. Notice using cached active index only supports single-selection mode, which means the result list has at most one index. @return: Active indexes list. """ # If use listbox widget's selected indexes if internal: # Return listbox widget's selected indexes list return [int(x) for x in self._listbox.curselection()] # If not use listbox widget's selected indexes else: # If cached active index is valid if self.index_is_valid(self._indexcur): # Return a list with the cached active index return [self._indexcur] # If cached active index is not valid else: # Return empty list return [] def indexcur_set( self, index, focus=False, notify=True, notify_arg=None, ): """ Set active index. @param index: The index to set. @param focus: Whether set focus on the listbox widget. @param notify: Whether notify pre-change and post-change events. @param notify_arg: Event argument. @return: None. """ # If the index is not valid or -1 if not self.index_is_valid_or_void(index): # Raise error raise IndexError(index) # If the index is valid or is -1. # If the listbox is not enabled if not self.is_enabled(): # Raise error raise ListboxVidget.DisabledError() # If the listbox is enabled. # If the listbox is changing if self._is_changing: # Raise error raise ListboxVidget.CircularCallError() # If the listbox is not changing. # Set changing flag on self._is_changing = True # Get old active index old_indexcur = self._indexcur # Set resetting flag on if new and old indexes are equal self._is_resetting = (index == old_indexcur) # If notify events if notify: # Notify pre-change event self.handler_notify(self.ITEMCUR_CHANGE_SOON, notify_arg) # If old active index is valid if self.index_is_valid(old_indexcur): # Set old active item's background color to normal color self._listbox.itemconfig(old_indexcur, background=self._normal_bg) # Set old active item's foreground color to normal color self._listbox.itemconfig(old_indexcur, foreground=self._normal_fg) # Cache new active index self._indexcur = index # Clear listbox widget's selection self._listbox.selection_clear(0, END) # Set listbox widget's selection self._listbox.selection_set(index) # Set listbox widget's activated index self._listbox.activate(index) # If new active index is valid if index != -1: # Set new active item's background color to active color self._listbox.itemconfig(index, background=self._active_bg) # Set new active item's foreground color to active color self._listbox.itemconfig(index, foreground=self._active_fg) # If set focus if focus: # Set focus on the listbox widget self._listbox.focus_set() # If new active index is valid if index != -1: # Make the active item visible self._listbox.see(index) # If notify events if notify: # Notify post-change event self.handler_notify(self.ITEMCUR_CHANGE_DONE, notify_arg) # Set resetting flag off self._is_resetting = False # Set changing flag off self._is_changing = False def indexcur_set_by_event( self, event, focus=False, notify=True, notify_arg=None, ): """ Set active index using a Tkinter event object that contains coordinates of the active item. @param event: Tkinter event object. @param focus: Whether set focus on the listbox widget. @param notify: Whether notify pre-change and post-change events. @param notify_arg: Event argument. @return: None. """ # Get the event's y co-ordinate's nearest listbox item index index = self._listbox.nearest(event.y) # If the index is not valid if not self.index_is_valid_or_void(index): # Ignore the event return # If the index is valid else: # Set the index as active index self.indexcur_set( index=index, focus=focus, notify=notify, notify_arg=notify_arg, ) def item(self, index): """ Get item at given index. @return: Item at given index, or IndexError if the index is not valid. """ return self.items()[index] def itemcur(self, internal=False, raise_error=False): """ Get the active item. @param internal: See 2N6OR. @param raise_error: Whether raise error if no active item. @return: The active item. If no active item, if `raise_error` is True, raise IndexError, otherwise return None. """ # Get active index. # May raise IndexError if `raise_error` is True. indexcur = self.indexcur( internal=internal, raise_error=raise_error, ) # If no active index if indexcur == -1: # Return None return None # If have active index else: # Return the active item return self.items()[indexcur] def item_insert( self, item, index=None, notify=True, keep_active=True, ): """ Insert item at given index. @param item: Item to insert. @param index: Index to insert. `None` means active index, and if no active index, insert at the end. @param notify: Whether notify pre-change and post-change events. @param keep_active: Whether keep or clear active index. @return: None. """ # If notify events if notify: # Notify pre-change events self.handler_notify(self.ITEMCUR_CHANGE_SOON) self.handler_notify(self.ITEMS_CHANGE_SOON) # Get old active index active_index = self.indexcur() # If the index is None, # it means use active index. if index is None: # Use active index. # `-1` works and means appending. index = active_index # Insert the item to the items list self._items.insert(index, item) # If old active index is valid if active_index != -1: # If old active index is GE the inserted index if active_index >= index: # Shift active index by one active_index += 1 # If old active index is not GE the inserted index, use it as-is. # Set new active index self.indexcur_set(index=active_index, notify=False) # Update listbox widget self._listbox_widget_update( keep_active=keep_active ) # If notify events if notify: # Notify post-change events self.handler_notify(self.ITEMS_CHANGE_DONE) self.handler_notify(self.ITEMCUR_CHANGE_DONE) def item_remove( self, index, notify=True, keep_active=True, ): """ Remove item at given index. @param index: Index to remove. @param notify: Whether notify pre-change and post-change events. @param keep_active: Whether keep or clear active index. @return: None. """ # If the index is not valid if not self.index_is_valid(index): # Raise error raise ValueError(index) # If the index is valid. # If notify events if notify: # Notify pre-change events self.handler_notify(self.ITEMCUR_CHANGE_SOON) self.handler_notify(self.ITEMS_CHANGE_SOON) # Get old active index active_index = self.indexcur() # Remove item at the index del self._items[index] # If old active index is valid if active_index != -1: # Get the last index index_last = self.index_last() # If old active index is GT the last index if active_index > index_last: # Use the last index as new active index active_index = index_last # If old active index is not GT the last index, use it as-is. # Set new active index self.indexcur_set(index=active_index, notify=False) # Update listbox widget self._listbox_widget_update( keep_active=keep_active ) # If notify events if notify: # Notify post-change events self.handler_notify(self.ITEMS_CHANGE_DONE) self.handler_notify(self.ITEMCUR_CHANGE_DONE) def handler_add( self, event, handler, need_arg=False, ): """ Add event handler for an event. If the event is ListboxVidget event, add the event handler to Eventor. If the event is not ListboxVidget event, add the event handler to listbox widget. Notice this method overrides `Eventor.handler_add` in order to add non-ListboxVidget event handler to listbox widget. @param event: Event name. @param handler: Event handler. @param need_arg: Whether the event handler needs event argument. @return: None. """ # If the event is ListboxVidget event if event in self.EVENTS: # Add the event handler to Eventor return Eventor.handler_add( self, event=event, handler=handler, need_arg=need_arg, ) # If the event is not ListboxVidget event, # it is assumed to be Tkinter widget event. else: # Add the event handler to listbox widget return self.bind( event=event, handler=handler, ) def bind( self, event, handler, ): """ Add event handler to listbox widget. ListboxVidget internally uses `<Button-1>` and `<Double-Button-1>` to capture active index changes. So if the given event is `<Button-1>` or `<Double-Button-1>`, the given handler will be wrapped. @param event: Event name. @param handler: Event handler. @return: None. """ # If the event is not `<Button-1>` or `<Double-Button-1>` if event not in ['<Button-1>', '<Double-Button-1>']: # Add the event handler to listbox widget self._listbox.bind(event, handler) # If the event is `<Button-1>` or `<Double-Button-1>` else: # Create event handler wrapper def handler_wrapper(e): """ Event handler wrapper that sets new active index and then calls the wrapped event handler. Setting new active index is needed because when this handler is called by Tkinter, the active index of the listbox is still old. @param e: Tkinter event object. @return: None. """ # Set new active index self.indexcur_set_by_event(e, notify=True) # Call the wrapped event handler handler(e) # Add the event handler wrapper to the listbox widget self._listbox.bind(event, handler_wrapper) def _on_single_click(self, event): """ `<Button-1>` event handler that updates active index. @param event: Tkinter event object. @return: None. """ # Updates active index self.indexcur_set_by_event(event, notify=True) def _on_double_click(self, event): """ `<Double-Button-1>` event handler that updates active index. @param event: Tkinter event object. @return: None. """ # Updates active index self.indexcur_set_by_event(event, notify=True) def _listbox_widget_update( self, keep_active, ): """ Update listbox widget's items and selection. @param keep_active: Whether keep or clear active index. @return: None. """ # Remove old items from listbox widget self._listbox.delete(0, END) # Insert new items into listbox widget. # For each ListboxVidget items. for index, item in enumerate(self.items()): # Get item text item_text = self._item_to_text(item) # Insert the item text into listbox widget self._listbox.insert(index, item_text) # Set the item's normal background color self._listbox.itemconfig(index, background=self._normal_bg) # Set the item's normal foreground color self._listbox.itemconfig(index, foreground=self._normal_fg) # Set the item's selected background color self._listbox.itemconfig(index, selectbackground=self._selected_bg) # Set the item's selected foreground color self._listbox.itemconfig(index, selectforeground=self._selected_fg) # If keep active index if keep_active: # Use old active index indexcur = self._indexcur # If not keep active index else: # Set active index to -1 indexcur = self._indexcur = -1 # Clear old selection self._listbox.selection_clear(0, END) # Set new selection. # `-1` works. self._listbox.selection_set(indexcur) # Set new active index. # `-1` works. self._listbox.activate(indexcur) # If new active index is valid if indexcur != -1: # Set active background color self._listbox.itemconfig(indexcur, background=self._active_bg) # Set active foreground color self._listbox.itemconfig(indexcur, foreground=self._active_fg) # Make the active item visible self._listbox.see(indexcur)
class AutoCompleteEntry(Entry): # pylint: disable=too-many-ancestors """ An entry widget with asdf. """ def __init__(self, autocomplete_list, *args, **kwargs): self.autocomplete_list = autocomplete_list self.list_box_length = kwargs.pop('list_box_length', 8) self.matches_function = kwargs.pop('matches_function', self._default_match) # function to initate_string_var_no_textvariable self.textvariable = kwargs.get('textvariable', StringVar()) self.list_box = None super().__init__(*args, **kwargs) self.config(textvariable=self.textvariable) self.focus() self.textvariable.trace('w', self._changed) @property def existing_list_box(self): """ Check if this instance has its' listbox defined/open. """ return self.__dict__.get('list_box', False) @staticmethod def _default_match(query, list_entry): """ The default match function if none is given during instantiation. """ pattern = re.compile(re.escape(query) + '.*', re.IGNORECASE) return re.match(pattern, list_entry) def _changed(self, name, index, mode): """ Event handler for changes to entry. """ print("in _changed") print(name, index, mode) if self.textvariable.get(): # not empty string words = self.__comparison() if not words: return self.__delete_existing_list_box() if not self.existing_list_box: self.list_box = Listbox(width=self["width"], height=self.list_box_length) # looks hacky self.list_box.place( x=self.winfo_x(), y=self.winfo_y() + self.winfo_height()) self.list_box.delete(0, END) for word in words: self.list_box.insert(END, word) else: self.__delete_existing_list_box() def __delete_existing_list_box(self): """ Deletes open listbox. """ if self.existing_list_box: self.list_box.destroy() # hmmmm def __comparison(self): """ Finds words similar to query. TODO """ if len(self.get()) < 3: return [] ans = [w for w in self.autocomplete_list if self.matches_function(self.textvariable.get(), w)] print(ans) return ans[:5]
class OptimizerMainWindow: """ classdocs """ # TODO: change that name def reactToClick(self, event): a = AddRestrictionDialog(self) def __init__(self, optimizer): # always have a reference to model/controller self.optimizer = optimizer # setup main GUI and make stretchable self.guiRoot = Tk() self.guiRoot.title("OPTIMIZR") self.guiRoot.columnconfigure(1, weight=1) self.guiRoot.rowconfigure(0, weight=1) # left (settings) and right (sequences) part self.frameLeft = Frame(self.guiRoot) self.frameLeft.grid(row=0, column=0, sticky=W + E + N + S) self.frameLeft.columnconfigure(0, weight=1) self.frameRight = Frame(self.guiRoot) self.frameRight.grid(row=0, column=1, sticky=W + E + N + S) self.frameRight.columnconfigure(0, weight=1) self.frameRight.rowconfigure(0, weight=1) self.frameRight.rowconfigure(1, weight=1) self.frameSpeciesControll = LabelFrame(self.frameLeft, text="Species", pady=10, padx=10) self.frameSpeciesControll.columnconfigure(1, weight=1) self.frameOptimizationControll = LabelFrame(self.frameLeft, text="Optimization", pady=10, padx=10) self.frameRestrictionControll = LabelFrame(self.frameLeft, text="Restriction Enzymes", pady=10, padx=10) self.frameSpeciesControll.grid(row=0, column=0, sticky=W + E, padx=10, pady=10) self.frameOptimizationControll.grid(row=1, column=0, sticky=W + E, padx=10, pady=10) self.frameRestrictionControll.grid(row=2, column=0, sticky=W + E, padx=10, pady=10) # Species Controll Label(self.frameSpeciesControll, text="Source:").grid(row=0, column=0) Label(self.frameSpeciesControll, text="Target:").grid(row=1, column=0) self.comboSourceSpecies = Combobox(self.frameSpeciesControll, state="readonly") self.comboSourceSpecies.grid(row=0, column=1, pady=5, sticky="ew") self.comboTargetSpecies = Combobox(self.frameSpeciesControll, state="readonly") self.comboTargetSpecies.grid(row=1, column=1, pady=5, sticky="we") self.buttonSpeciesList = Button(self.frameSpeciesControll, text="Edit Species List") self.buttonSpeciesList.grid(row=2, column=1, pady=5, sticky="e") self.comboSourceSpecies.bind("<<ComboboxSelected>>", self.actionOptimizerSettingsChanged) self.comboTargetSpecies.bind("<<ComboboxSelected>>", self.actionOptimizerSettingsChanged) # Optimization Controll Label(self.frameOptimizationControll, text="Optimization Strategy:").grid(row=0, column=0) self.comboOptimizationStrategy = Combobox(self.frameOptimizationControll, state="readonly") self.comboOptimizationStrategy.grid(row=0, column=1) self.comboOptimizationStrategy["values"] = self.optimizer.possibleOptimizationStrategies self.comboOptimizationStrategy.bind("<<ComboboxSelected>>", self.actionOptimizerSettingsChanged) # Restriction Enzymes self.listRestriction = Listbox(self.frameRestrictionControll) self.listRestriction.grid(row=0, column=0, columnspan=3, pady=5, sticky=W + E) self.frameRestrictionControll.columnconfigure(0, weight=1) self.buttonRestricionAdd = Button(self.frameRestrictionControll, text=" + ") self.buttonRestricionDel = Button(self.frameRestrictionControll, text=" - ") self.buttonRestricionAdd.grid(row=1, column=1, padx=5) self.buttonRestricionDel.grid(row=1, column=2, padx=5) # Source Sequence Frame self.frameSourceSequence = LabelFrame(self.frameRight, text="Source Sequence", padx=10, pady=10) self.frameResultSequence = LabelFrame(self.frameRight, text="Result Sequence", padx=10, pady=10) self.frameSourceSequence.grid(row=0, column=0, sticky="wens", padx=10, pady=10) self.frameResultSequence.grid(row=1, column=0, sticky="wens", padx=10, pady=10) self.buttonSourceLoad = Button(self.frameSourceSequence, text=" Load ") self.textSourceSeq = ScrolledText(self.frameSourceSequence, height=10) self.buttonSourceLoad.grid(row=0, column=1, sticky="e", pady=5) self.textSourceSeq.grid(row=1, column=0, columnspan=2, sticky="wens") self.frameSourceSequence.columnconfigure(0, weight=1) self.frameSourceSequence.rowconfigure(1, weight=1) self.textSourceSeq.frame.columnconfigure(1, weight=1) self.textSourceSeq.frame.rowconfigure(0, weight=1) self.buttonOptimize = Button(self.frameResultSequence, text=" OPTIMIZE! ") self.buttonOptimize.bind("<ButtonRelease>", self.actionOptimize) self.buttonRemoveRestriction = Button(self.frameResultSequence, text=" RESTRICTION-B-GONE! ") self.buttonRemoveRestriction.bind("<ButtonRelease>", self.actionRemoveRestricion) self.buttonSaveResult = Button(self.frameResultSequence, text=" Save ") self.textResultSequence = ScrolledText(self.frameResultSequence, height=10) self.buttonOptimize.grid(column=0, row=0, pady=5, sticky="w") self.buttonRemoveRestriction.grid(column=1, row=0, pady=5, padx=10, sticky="w") self.textResultSequence.grid(row=1, column=0, columnspan=4, sticky="wens") self.buttonSaveResult.grid(row=2, column=3, pady=5, sticky="e") self.frameResultSequence.columnconfigure(2, weight=1) self.frameResultSequence.rowconfigure(1, weight=1) self.textResultSequence.frame.columnconfigure(1, weight=1) self.textResultSequence.frame.rowconfigure(0, weight=1) self.textSourceSeq.bind("<<Modified>>", self.actionSequenceModified) self.textResultSequence.bind("<<Modified>>", self.actionSequenceModified) # generate color tags for textboxes for i in range(101): # green for normal codons (r, g, b) = colorsys.hsv_to_rgb(210 / 360, i / 100, 1.0) colorHex = "#%02x%02x%02x" % (int(r * 255), int(g * 255), int(b * 255)) self.textSourceSeq.tag_config("normal" + str(i), background=colorHex) self.textResultSequence.tag_config("normal" + str(i), background=colorHex) # red for codons with restriction sites (r, g, b) = colorsys.hsv_to_rgb(5 / 360, i / 100, 1.0) colorHex = "#%02x%02x%02x" % (int(r * 255), int(g * 255), int(b * 255)) self.textSourceSeq.tag_config("restrict" + str(i), background=colorHex) self.textResultSequence.tag_config("restrict" + str(i), background=colorHex) # Set (minimum + max) Window size self.guiRoot.update() self.guiRoot.minsize(self.guiRoot.winfo_width(), self.guiRoot.winfo_height()) self.buttonRestricionAdd.bind("<ButtonRelease>", self.reactToClick) self.buttonRestricionDel.bind("<ButtonRelease>", self.actionRestrictionEnzymeDelete) self.buttonSpeciesList.bind("<ButtonRelease>", self.actionEditSpeciesButton) self.buttonSourceLoad.bind("<ButtonRelease>", self.actionLoadSequence) self.buttonSaveResult.bind("<ButtonRelease>", self.actionSaveSequence) # TEST # self.listRestriction.insert("end", "EcoRI") # self.listRestriction.insert("end", "BamHI") # # dummy event to manually trigger update self.guiRoot.bind("<<Update>>", self.actionUpdate) self.actionUpdate(None) self.guiRoot.mainloop() def actionRestrictionEnzymeDelete(self, event): try: selectedEnzyme = self.listRestriction.selection_get() self.optimizer.restrictionEnzymeList.remove(selectedEnzyme) self.guiRoot.event_generate("<<Update>>") except tkinter.TclError: # no selection pass def actionUpdate(self, event): # print("update called") # clear list of restriction enzymes self.listRestriction.delete(0, "end") for r in self.optimizer.restrictionEnzymeList: self.listRestriction.insert("end", r) self.comboSourceSpecies.delete(0, "end") self.comboTargetSpecies.delete(0, "end") speciesValues = list() for (taxid, name) in self.optimizer.speciesList: speciesValues.append(taxid + ": " + name) self.comboSourceSpecies["values"] = speciesValues self.comboTargetSpecies["values"] = speciesValues if self.comboSourceSpecies.get() not in speciesValues: self.comboSourceSpecies.set("") if self.comboTargetSpecies.get() not in speciesValues: self.comboTargetSpecies.set("") self.textSourceSeq.edit_modified(True) self.textResultSequence.edit_modified(True) self.optimizer.saveConfig("config.ini") def actionEditSpeciesButton(self, event): speciesListDialog = SpeciesListDialog(self) def actionOptimizerSettingsChanged(self, event=None): # print("Something happened") strategy = self.comboOptimizationStrategy.get() sourceString = self.comboSourceSpecies.get() targetString = self.comboTargetSpecies.get() if not (strategy and sourceString and targetString): return sourceTaxid = sourceString.split(":")[0] targetTaxid = targetString.split(":")[0] self.optimizer.setOptimizer(sourceTaxid, targetTaxid, strategy) self.textSourceSeq.edit_modified(True) self.textResultSequence.edit_modified(True) # self.optimizer.testPrint() def actionOptimize(self, event=None): self.optimizer.runOptimization() self.textSourceSeq.edit_modified(True) self.textResultSequence.edit_modified(True) def actionRemoveRestricion(self, event=None): self.optimizer.runRestricionRemoval() self.textSourceSeq.edit_modified(True) self.textResultSequence.edit_modified(True) def actionSequenceModified(self, event=None): # necessary if, otherwise -> infinite loop if self.textSourceSeq.edit_modified(): seq = self.textSourceSeq.get("1.0", "end").strip() seq = stripCharsNotInList(seq.upper(), ["A", "C", "G", "T"]) self.optimizer.setSourceSeq(seq) oldInsert = self.textSourceSeq.index("insert") self.textSourceSeq.delete("1.0", "end") sourceCodons = self.optimizer.getCodonsForPrint(True) if not sourceCodons: self.textSourceSeq.insert("end", self.optimizer.sourceSequence) else: for (co, sc, r) in sourceCodons: if sc: if not r: self.textSourceSeq.insert("end", co, "normal" + str(int(sc * 100))) # print("normal"+str(int(sc*100))) else: self.textSourceSeq.insert("end", co, "restrict" + str(int(sc * 100))) else: # remainder without color self.textSourceSeq.insert("end", co) self.textSourceSeq.mark_set("insert", oldInsert) # reset the modified status at the very end self.textSourceSeq.edit_modified(False) if self.textResultSequence.edit_modified(): seq = self.textResultSequence.get("1.0", "end").strip() # self.optimizer.setOptimizedSeq(seq) oldInsert = self.textResultSequence.index("insert") self.textResultSequence.delete("1.0", "end") targetCodons = self.optimizer.getCodonsForPrint(False) if not targetCodons: self.textSourceSeq.insert("end", self.optimizer.optimizedSequence) else: for (co, sc, r) in targetCodons: if sc: if not r: self.textResultSequence.insert("end", co, "normal" + str(int(sc * 100))) # print("normal"+str(int(sc*100))) else: self.textResultSequence.insert("end", co, "restrict" + str(int(sc * 100))) else: # remainder without color self.textResultSequence.insert("end", co) self.textSourceSeq.mark_set("insert", oldInsert) self.textResultSequence.edit_modified(False) def actionLoadSequence(self, event=None): filename = tkinter.filedialog.askopenfilename() if filename: seq = sequenceIO.readFile(filename) self.textSourceSeq.delete("1.0", "end") self.textSourceSeq.insert("end", seq) self.textSourceSeq.edit_modified(True) def actionSaveSequence(self, event=None): filename = tkinter.filedialog.asksaveasfilename() if filename: # print("file is " + filename) with open(filename, mode="w") as fd: fd.write(self.optimizer.optimizedSequence)
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 LintGui: """Build and control a window to interact with pylint""" def __init__(self, root=None): """init""" self.root = root or Tk() self.root.title("Pylint") # reporter self.reporter = None # message queue for output from reporter self.msg_queue = queue.Queue() self.msgs = [] self.filenames = [] self.rating = StringVar() self.tabs = {} self.report_stream = BasicStream(self) # gui objects self.lbMessages = None self.showhistory = None self.results = None self.btnRun = None self.information_box = None self.convention_box = None self.refactor_box = None self.warning_box = None self.error_box = None self.fatal_box = None self.txtModule = None self.status = None self.msg_type_dict = None self.init_gui() def init_gui(self): """init helper""" # setting up frames top_frame = Frame(self.root) mid_frame = Frame(self.root) radio_frame = Frame(self.root) res_frame = Frame(self.root) msg_frame = Frame(self.root) check_frame = Frame(self.root) history_frame = Frame(self.root) btn_frame = Frame(self.root) rating_frame = Frame(self.root) top_frame.pack(side=TOP, fill=X) mid_frame.pack(side=TOP, fill=X) history_frame.pack(side=TOP, fill=BOTH, expand=True) radio_frame.pack(side=TOP, fill=BOTH, expand=True) rating_frame.pack(side=TOP, fill=BOTH, expand=True) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=BOTH, expand=True) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) # Message ListBox rightscrollbar = Scrollbar(msg_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(msg_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.lbMessages = Listbox( msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white" ) self.lbMessages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lbMessages.yview) bottomscrollbar.config(command=self.lbMessages.xview) # History ListBoxes rightscrollbar2 = Scrollbar(history_frame) rightscrollbar2.pack(side=RIGHT, fill=Y) bottomscrollbar2 = Scrollbar(history_frame, orient=HORIZONTAL) bottomscrollbar2.pack(side=BOTTOM, fill=X) self.showhistory = Listbox( history_frame, yscrollcommand=rightscrollbar2.set, xscrollcommand=bottomscrollbar2.set, bg="white" ) self.showhistory.pack(expand=True, fill=BOTH) rightscrollbar2.config(command=self.showhistory.yview) bottomscrollbar2.config(command=self.showhistory.xview) self.showhistory.bind("<Double-Button-1>", self.select_recent_file) self.set_history_window() # status bar self.status = Label(self.root, text="", bd=1, relief=SUNKEN, anchor=W) self.status.pack(side=BOTTOM, fill=X) # labels self.lblRatingLabel = Label(rating_frame, text="Rating:") self.lblRatingLabel.pack(side=LEFT) self.lblRating = Label(rating_frame, textvariable=self.rating) self.lblRating.pack(side=LEFT) Label(mid_frame, text="Recently Used:").pack(side=LEFT) Label(top_frame, text="Module or package").pack(side=LEFT) # file textbox self.txtModule = Entry(top_frame, background="white") self.txtModule.bind("<Return>", self.run_lint) self.txtModule.pack(side=LEFT, expand=True, fill=X) # results box rightscrollbar = Scrollbar(res_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(res_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.results = Listbox( res_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white", font="Courier" ) self.results.pack(expand=True, fill=BOTH, side=BOTTOM) rightscrollbar.config(command=self.results.yview) bottomscrollbar.config(command=self.results.xview) # buttons Button(top_frame, text="Open", command=self.file_open).pack(side=LEFT) Button(top_frame, text="Open Package", command=(lambda: self.file_open(package=True))).pack(side=LEFT) self.btnRun = Button(top_frame, text="Run", command=self.run_lint) self.btnRun.pack(side=LEFT) Button(btn_frame, text="Quit", command=self.quit).pack(side=BOTTOM) # radio buttons self.information_box = IntVar() self.convention_box = IntVar() self.refactor_box = IntVar() self.warning_box = IntVar() self.error_box = IntVar() self.fatal_box = IntVar() i = Checkbutton( check_frame, text="Information", fg=COLORS["(I)"], variable=self.information_box, command=self.refresh_msg_window, ) c = Checkbutton( check_frame, text="Convention", fg=COLORS["(C)"], variable=self.convention_box, command=self.refresh_msg_window, ) r = Checkbutton( check_frame, text="Refactor", fg=COLORS["(R)"], variable=self.refactor_box, command=self.refresh_msg_window ) w = Checkbutton( check_frame, text="Warning", fg=COLORS["(W)"], variable=self.warning_box, command=self.refresh_msg_window ) e = Checkbutton( check_frame, text="Error", fg=COLORS["(E)"], variable=self.error_box, command=self.refresh_msg_window ) f = Checkbutton( check_frame, text="Fatal", fg=COLORS["(F)"], variable=self.fatal_box, command=self.refresh_msg_window ) i.select() c.select() r.select() w.select() e.select() f.select() i.pack(side=LEFT) c.pack(side=LEFT) r.pack(side=LEFT) w.pack(side=LEFT) e.pack(side=LEFT) f.pack(side=LEFT) # check boxes self.box = StringVar() # XXX should be generated report = Radiobutton( radio_frame, text="Report", variable=self.box, value="Report", command=self.refresh_results_window ) rawMet = Radiobutton( radio_frame, text="Raw metrics", variable=self.box, value="Raw metrics", command=self.refresh_results_window ) dup = Radiobutton( radio_frame, text="Duplication", variable=self.box, value="Duplication", command=self.refresh_results_window ) ext = Radiobutton( radio_frame, text="External dependencies", variable=self.box, value="External dependencies", command=self.refresh_results_window, ) stat = Radiobutton( radio_frame, text="Statistics by type", variable=self.box, value="Statistics by type", command=self.refresh_results_window, ) msgCat = Radiobutton( radio_frame, text="Messages by category", variable=self.box, value="Messages by category", command=self.refresh_results_window, ) msg = Radiobutton( radio_frame, text="Messages", variable=self.box, value="Messages", command=self.refresh_results_window ) report.select() report.grid(column=0, row=0, sticky=W) rawMet.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=E) stat.grid(column=0, row=1, sticky=W) msgCat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, columnspan=2, sticky=W) # dictionary for check boxes and associated error term self.msg_type_dict = { "I": lambda: self.information_box.get() == 1, "C": lambda: self.convention_box.get() == 1, "R": lambda: self.refactor_box.get() == 1, "E": lambda: self.error_box.get() == 1, "W": lambda: self.warning_box.get() == 1, "F": lambda: self.fatal_box.get() == 1, } self.txtModule.focus_set() def select_recent_file(self, event): """adds the selected file in the history listbox to the Module box""" if not self.showhistory.size(): return selected = self.showhistory.curselection() item = self.showhistory.get(selected) # update module self.txtModule.delete(0, END) self.txtModule.insert(0, item) def refresh_msg_window(self): """refresh the message window with current output""" # clear the window self.lbMessages.delete(0, END) for msg in self.msgs: if self.msg_type_dict.get(msg[0])(): msg_str = self.convert_to_string(msg) self.lbMessages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], "black") self.lbMessages.itemconfigure(END, fg=fg_color) def refresh_results_window(self): """refresh the results window with current output""" # clear the window self.results.delete(0, END) try: for res in self.tabs[self.box.get()]: self.results.insert(END, res) except: pass def convert_to_string(self, msg): """make a string representation of a message""" if msg[2] != "": return "(" + msg[0] + ") " + msg[1] + "." + msg[2] + " [" + msg[3] + "]: " + msg[4] else: return "(" + msg[0] + ") " + msg[1] + " [" + msg[3] + "]: " + msg[4] def process_incoming(self): """process the incoming messages from running pylint""" while self.msg_queue.qsize(): try: msg = self.msg_queue.get(0) if msg == "DONE": self.report_stream.output_contents() return False # adding message to list of msgs self.msgs.append(msg) # displaying msg if message type is selected in check box if self.msg_type_dict.get(msg[0])(): msg_str = self.convert_to_string(msg) self.lbMessages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], "black") self.lbMessages.itemconfigure(END, fg=fg_color) except queue.Empty: pass return True def periodic_call(self): """determine when to unlock the run button""" if self.process_incoming(): self.root.after(100, self.periodic_call) else: # enabling button so it can be run again self.btnRun.config(state=NORMAL) def mainloop(self): """launch the mainloop of the application""" self.root.mainloop() def quit(self, _=None): """quit the application""" self.root.quit() def halt(self): """program halt placeholder""" return def file_open(self, package=False, _=None): """launch a file browser""" if not package: filename = askopenfilename( parent=self.root, filetypes=[("pythonfiles", "*.py"), ("allfiles", "*")], title="Select Module" ) else: filename = askdirectory(title="Select A Folder", mustexist=1) if filename == (): return self.txtModule.delete(0, END) self.txtModule.insert(0, filename) def update_filenames(self): """update the list of recent filenames""" filename = self.txtModule.get() if not filename: filename = os.getcwd() if filename + "\n" in self.filenames: index = self.filenames.index(filename + "\n") self.filenames.pop(index) # ensure only 10 most recent are stored if len(self.filenames) == 10: self.filenames.pop() self.filenames.insert(0, filename + "\n") def set_history_window(self): """update the history window with info from the history file""" # clear the window self.showhistory.delete(0, END) # keep the last 10 most recent files try: view_history = open(HOME + HISTORY, "r") for hist in view_history.readlines(): if not hist in self.filenames: self.filenames.append(hist) self.showhistory.insert(END, hist.split("\n")[0]) view_history.close() except IOError: # do nothing since history file will be created later return def run_lint(self, _=None): """launches pylint""" self.update_filenames() self.root.configure(cursor="watch") self.reporter = GUIReporter(self, output=self.report_stream) module = self.txtModule.get() if not module: module = os.getcwd() # cleaning up msgs and windows self.msgs = [] self.lbMessages.delete(0, END) self.tabs = {} self.results.delete(0, END) self.btnRun.config(state=DISABLED) # setting up a worker thread to run pylint worker = Thread(target=lint_thread, args=(module, self.reporter, self)) self.periodic_call() worker.start() # Overwrite the .pylint-gui-history file with all the new recently added files # in order from filenames but only save last 10 files write_history = open(HOME + HISTORY, "w") write_history.writelines(self.filenames) write_history.close() self.set_history_window() self.root.configure(cursor="")
class AutocompleteEntry(Entry): def __init__(self, *args, **kwargs): Entry.__init__(self, width=100, *args, **kwargs) self.focus_set() self.pack() self.var = self["textvariable"] if self.var == '': self.var = self["textvariable"] = StringVar() self.var.trace('w', self.changed) self.bind("<Right>", self.selection) self.bind("<Up>", self.up) self.bind("<Down>", self.down) self.bind("<Return>", self.enter) self.lb_up = False self.lb = None def enter(self, event): print(event) def changed(self, name, index, mode): if self.var.get() == '': if self.lb: self.lb.destroy() self.lb_up = False else: words = self.comparison() if words: if not self.lb_up: self.lb = Listbox(master=root, width=100) self.lb.bind("<Double-Button-1>", self.selection) self.lb.bind("<Right>", self.selection) self.lb.place(x=self.winfo_x(), y=self.winfo_y()+self.winfo_height()) self.lb_up = True self.lb.delete(0, END) for w in words: self.lb.insert(END,w) else: if self.lb_up: self.lb.destroy() self.lb_up = False def selection(self, _): if self.lb_up: self.var.set(self.lb.get(ACTIVE)) self.lb.destroy() self.lb_up = False self.icursor(END) def up(self, _): if self.lb_up: if self.lb.curselection() == (): index = '0' else: index = self.lb.curselection()[0] if index != '0': self.lb.selection_clear(first=index) index = str(int(index)-1) self.lb.selection_set(first=index) self.lb.activate(index) def down(self, _): if self.lb_up: if self.lb.curselection() == (): index = '0' else: index = self.lb.curselection()[0] if index != END: self.lb.selection_clear(first=index) index = str(int(index)+1) self.lb.selection_set(first=index) self.lb.activate(index) def comparison(self): q = self.var.get() q = str(q.decode('utf8')) for hit in searcher.search(qp.parse(q), limit=50): if hit['author']: yield '%s. "%s"' % (hit['author'], hit['title']) else: yield hit['title']
class Add_Recipe_Modal(Modal): def __init__(self, parent=None, title="Add Recipe"): self.shorts = [] self.amounts = None self.ingredients = None Modal.__init__(self, parent, title, geometry="375x410" if system() == "Windows" else "375x350") def initialize(self): amount_label = Label(self, width=8, text="Amount") amount_label.grid(row=0, column=0) ingredients_label = Label(self, width=35, text="Item Name") ingredients_label.grid(row=0, column=1) self.amounts_list = Listbox(self, width=8, selectmode="single") self.amounts_list.bind("<Double-Button-1>", self.edit) self.amounts_list.grid(row=1, column=0, sticky="E") self.ingredients_list = Listbox(self, width=35, selectmode="single") self.ingredients_list.bind("<Double-Button-1>", self.edit) self.ingredients_list.grid(row=1, column=1) add_button = Button(self, width=7, text="Add", command=self.add) self.bind("<Control-+>", self.add) self.bind("<Insert>", self.add) add_button.grid(row=2, column=1, sticky="E") remove_button = Button(self, text="Remove", command=self.remove) self.bind("<Delete>", self.remove) remove_button.grid(row=2, column=0) produces_label = Label(self, text="Produces: ") produces_label.grid(row=3, column=0, sticky="W") self.produces_box = Entry(self, width=5) self.produces_box.insert(0, "1") self.produces_box.grid(row=3, column=1, sticky="W") machine_label = Label(self, text="Machine: ") machine_label.grid(row=4, column=0, sticky="W") self.machine_box = Entry(self) self.machine_box.grid(row=4, column=1, sticky="EW") info_label = Label(self, text="Extra Info: ") info_label.grid(row=5, column=0, sticky="W") self.info_box = Entry(self) self.info_box.grid(row=5, column=1, sticky="EW") cancel_button = Button(self, text="Cancel", width=7, command=self.cancel) self.bind("<Escape>", self.cancel) cancel_button.grid(row=6, column=0, pady=10) ok_button = Button(self, text="OK", width=7, command=self.ok) self.bind("<Return>", self.ok) ok_button.grid(row=6, column=1, pady=10, sticky="E") self.bind("<<ListboxSelect>>", self.sync) def sync(self, event): if event.widget is self.amounts_list and len(self.amounts_list.curselection()) != 0: self.ingredients_list.selection_set(self.amounts_list.curselection()[0]) def add(self, event=None): short, name, amount = Add_Ingredient_Modal().show() if short is not None and name is not None and amount is not None: if name not in self.ingredients_list.get(0, "end"): self.ingredients_list.insert("end", name) self.amounts_list.insert("end", amount) self.shorts.append(short) def edit(self, event=None): if len(self.ingredients_list.curselection()) != 0: index = self.ingredients_list.curselection()[0] current_short = self.shorts[index] current_name = self.ingredients_list.get(index) current_amount = self.amounts_list.get(index) new_short, new_name, new_amount = Edit_Ingredient_Modal().show(current_short, current_name, current_amount) if new_short is not None and new_name is not None and new_amount is not None: self.amounts_list.delete(index) self.ingredients_list.delete(index) self.amounts_list.insert(index, new_amount) self.ingredients_list.insert(index, new_name) self.shorts[index] = new_short def remove(self, event=None): if len(self.ingredients_list.curselection()) != 0: slct = int(self.ingredients_list.curselection()[0]) self.ingredients_list.delete(slct) self.amounts_list.delete(slct) del(self.shorts[slct]) def ok(self, event=None): if len(self.ingredients_list.get(0)) != 0 and self.produces_box is not None and self.produces_box.get().isdigit(): self.produces = int(self.produces_box.get()) self.amounts = self.amounts_list.get(0, last="end") self.ingredients = self.ingredients_list.get(0, last="end") self.machine = self.machine_box.get() self.info = self.info_box.get() self.destroy() def cancel(self, event=None): self.amounts = None self.ingredients = None self.shorts = None self.produces = None self.machine = None self.info = None self.destroy() def show(self): Modal.show(self) return self.shorts, self.ingredients, self.amounts, self.produces, self.machine, self.info
class DrtGlueDemo(object): def __init__(self, examples): # Set up the main window. self._top = Tk() self._top.title("DRT Glue Demo") # Set up key bindings. self._init_bindings() # Initialize the fonts.self._error = None self._init_fonts(self._top) self._examples = examples self._readingCache = [None for example in examples] # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Set the data to None self._curExample = -1 self._readings = [] self._drs = None self._drsWidget = None self._error = None self._init_glue() # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_exampleListbox(self._top) self._init_readingListbox(self._top) self._init_canvas(self._top) # Resize callback self._canvas.bind("<Configure>", self._configure) ######################################### ## Initialization Helpers ######################################### def _init_glue(self): tagger = RegexpTagger( [ ("^(David|Mary|John)$", "NNP"), ("^(walks|sees|eats|chases|believes|gives|sleeps|chases|persuades|tries|seems|leaves)$", "VB"), ("^(go|order|vanish|find|approach)$", "VB"), ("^(a)$", "ex_quant"), ("^(every)$", "univ_quant"), ("^(sandwich|man|dog|pizza|unicorn|cat|senator)$", "NN"), ("^(big|gray|former)$", "JJ"), ("^(him|himself)$", "PRP"), ] ) depparser = MaltParser(tagger=tagger) self._glue = DrtGlue(depparser=depparser, remove_duplicates=False) def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget("size")) self._boldfont = Font(family="helvetica", weight="bold", size=self._size.get()) self._font = Font(family="helvetica", size=self._size.get()) if self._size.get() < 0: big = self._size.get() - 2 else: big = self._size.get() + 2 self._bigfont = Font(family="helvetica", weight="bold", size=big) def _init_exampleListbox(self, parent): self._exampleFrame = listframe = Frame(parent) self._exampleFrame.pack(fill="both", side="left", padx=2) self._exampleList_label = Label(self._exampleFrame, font=self._boldfont, text="Examples") self._exampleList_label.pack() self._exampleList = Listbox( self._exampleFrame, selectmode="single", relief="groove", background="white", foreground="#909090", font=self._font, selectforeground="#004040", selectbackground="#c0f0c0", ) self._exampleList.pack(side="right", fill="both", expand=1) for example in self._examples: self._exampleList.insert("end", (" %s" % example)) self._exampleList.config(height=min(len(self._examples), 25), width=40) # Add a scrollbar if there are more than 25 examples. if len(self._examples) > 25: listscroll = Scrollbar(self._exampleFrame, orient="vertical") self._exampleList.config(yscrollcommand=listscroll.set) listscroll.config(command=self._exampleList.yview) listscroll.pack(side="left", fill="y") # If they select a example, apply it. self._exampleList.bind("<<ListboxSelect>>", self._exampleList_select) def _init_readingListbox(self, parent): self._readingFrame = listframe = Frame(parent) self._readingFrame.pack(fill="both", side="left", padx=2) self._readingList_label = Label(self._readingFrame, font=self._boldfont, text="Readings") self._readingList_label.pack() self._readingList = Listbox( self._readingFrame, selectmode="single", relief="groove", background="white", foreground="#909090", font=self._font, selectforeground="#004040", selectbackground="#c0f0c0", ) self._readingList.pack(side="right", fill="both", expand=1) # Add a scrollbar if there are more than 25 examples. listscroll = Scrollbar(self._readingFrame, orient="vertical") self._readingList.config(yscrollcommand=listscroll.set) listscroll.config(command=self._readingList.yview) listscroll.pack(side="right", fill="y") self._populate_readingListbox() def _populate_readingListbox(self): # Populate the listbox with integers self._readingList.delete(0, "end") for i in range(len(self._readings)): self._readingList.insert("end", (" %s" % (i + 1))) self._readingList.config(height=min(len(self._readings), 25), width=5) # If they select a example, apply it. self._readingList.bind("<<ListboxSelect>>", self._readingList_select) def _init_bindings(self): # Key bindings are a good thing. self._top.bind("<Control-q>", self.destroy) self._top.bind("<Control-x>", self.destroy) self._top.bind("<Escape>", self.destroy) self._top.bind("n", self.next) self._top.bind("<space>", self.next) self._top.bind("p", self.prev) self._top.bind("<BackSpace>", self.prev) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill="none", side="bottom", padx=3, pady=2) Button(buttonframe, text="Prev", background="#90c0d0", foreground="black", command=self.prev).pack(side="left") Button(buttonframe, text="Next", background="#90c0d0", foreground="black", command=self.next).pack(side="left") def _configure(self, event): self._autostep = 0 (x1, y1, x2, y2) = self._cframe.scrollregion() y2 = event.height - 6 self._canvas["scrollregion"] = "%d %d %d %d" % (x1, y1, x2, y2) self._redraw() def _init_canvas(self, parent): self._cframe = CanvasFrame( parent, background="white", # width=525, height=250, closeenough=10, border=2, relief="sunken", ) self._cframe.pack(expand=1, fill="both", side="top", pady=2) canvas = self._canvas = self._cframe.canvas() # Initially, there's no tree or text self._tree = None self._textwidgets = [] self._textline = None def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label="Exit", underline=1, command=self.destroy, accelerator="q") menubar.add_cascade(label="File", underline=0, menu=filemenu) actionmenu = Menu(menubar, tearoff=0) actionmenu.add_command(label="Next", underline=0, command=self.next, accelerator="n, Space") actionmenu.add_command(label="Previous", underline=0, command=self.prev, accelerator="p, Backspace") menubar.add_cascade(label="Action", underline=0, menu=actionmenu) optionmenu = Menu(menubar, tearoff=0) optionmenu.add_checkbutton( label="Remove Duplicates", underline=0, variable=self._glue.remove_duplicates, command=self._toggle_remove_duplicates, accelerator="r", ) menubar.add_cascade(label="Options", underline=0, menu=optionmenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_radiobutton(label="Tiny", variable=self._size, underline=0, value=10, command=self.resize) viewmenu.add_radiobutton(label="Small", variable=self._size, underline=0, value=12, command=self.resize) viewmenu.add_radiobutton(label="Medium", variable=self._size, underline=0, value=14, command=self.resize) viewmenu.add_radiobutton(label="Large", variable=self._size, underline=0, value=18, command=self.resize) viewmenu.add_radiobutton(label="Huge", variable=self._size, underline=0, value=24, command=self.resize) menubar.add_cascade(label="View", underline=0, menu=viewmenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label="About", underline=0, command=self.about) menubar.add_cascade(label="Help", underline=0, menu=helpmenu) parent.config(menu=menubar) ######################################### ## Main draw procedure ######################################### def _redraw(self): canvas = self._canvas # Delete the old DRS, widgets, etc. if self._drsWidget is not None: self._drsWidget.clear() if self._drs: self._drsWidget = DrsWidget(self._canvas, self._drs) self._drsWidget.draw() if self._error: self._drsWidget = DrsWidget(self._canvas, self._error) self._drsWidget.draw() ######################################### ## Button Callbacks ######################################### def destroy(self, *e): self._autostep = 0 if self._top is None: return self._top.destroy() self._top = None def prev(self, *e): selection = self._readingList.curselection() readingListSize = self._readingList.size() # there are readings if readingListSize > 0: # if one reading is currently selected if len(selection) == 1: index = int(selection[0]) # if it's on (or before) the first item if index <= 0: self._select_previous_example() else: self._readingList_store_selection(index - 1) else: # select its first reading self._readingList_store_selection(readingListSize - 1) else: self._select_previous_example() def _select_previous_example(self): # if the current example is not the first example if self._curExample > 0: self._exampleList_store_selection(self._curExample - 1) else: # go to the last example self._exampleList_store_selection(len(self._examples) - 1) def next(self, *e): selection = self._readingList.curselection() readingListSize = self._readingList.size() # if there are readings if readingListSize > 0: # if one reading is currently selected if len(selection) == 1: index = int(selection[0]) # if it's on (or past) the last item if index >= (readingListSize - 1): self._select_next_example() else: self._readingList_store_selection(index + 1) else: # select its first reading self._readingList_store_selection(0) else: self._select_next_example() def _select_next_example(self): # if the current example is not the last example if self._curExample < len(self._examples) - 1: self._exampleList_store_selection(self._curExample + 1) else: # go to the first example self._exampleList_store_selection(0) def about(self, *e): ABOUT = "NLTK Discourse Representation Theory (DRT) Glue Semantics Demo\n" + "Written by Daniel H. Garrette" TITLE = "About: NLTK DRT Glue Demo" try: from tkMessageBox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def postscript(self, *e): self._autostep = 0 self._cframe.print_to_file() def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs) def resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) self._bigfont.configure(size=-(abs(size + 2))) self._redraw() def _toggle_remove_duplicates(self): self._glue.remove_duplicates = not self._glue.remove_duplicates self._exampleList.selection_clear(0, "end") self._readings = [] self._populate_readingListbox() self._readingCache = [None for ex in self._examples] self._curExample = -1 self._error = None self._drs = None self._redraw() def _exampleList_select(self, event): selection = self._exampleList.curselection() if len(selection) != 1: return self._exampleList_store_selection(int(selection[0])) def _exampleList_store_selection(self, index): self._curExample = index example = self._examples[index] self._exampleList.selection_clear(0, "end") if example: cache = self._readingCache[index] if cache: if isinstance(cache, list): self._readings = cache self._error = None else: self._readings = [] self._error = cache else: try: self._readings = self._glue.parse_to_meaning(example) self._error = None self._readingCache[index] = self._readings except Exception as e: self._readings = [] self._error = DrtVariableExpression(Variable("Error: " + str(e))) self._readingCache[index] = self._error # add a star to the end of the example self._exampleList.delete(index) self._exampleList.insert(index, (" %s *" % example)) self._exampleList.config(height=min(len(self._examples), 25), width=40) self._populate_readingListbox() self._exampleList.selection_set(index) self._drs = None self._redraw() def _readingList_select(self, event): selection = self._readingList.curselection() if len(selection) != 1: return self._readingList_store_selection(int(selection[0])) def _readingList_store_selection(self, index): reading = self._readings[index] self._readingList.selection_clear(0, "end") if reading: self._readingList.selection_set(index) self._drs = reading.simplify().normalize().resolve_anaphora() self._redraw()
class Controller: SNAP_RADIUS = 5 def __init__(self, tk: Tk): tk.title("Layered Polygons") menubar = Menu(tk) menu_file = Menu(menubar, tearoff=0) menu_file.add_command(label="New...", command=self._new_scene) menu_file.add_command(label="Open...", command=self._open_scene) menu_file.add_separator() menu_file.add_command(label="Save", command=self._save_scene) menu_file.add_command(label="Save As...", command=self._save_scene_as) menu_file.add_separator() menu_export = Menu(menu_file, tearoff=0) menu_export.add_command(label="Wavefront (.obj)...", command=self._export_obj) menu_file.add_cascade(label="Export As", menu=menu_export) menu_file.add_separator() menu_file.add_command(label="Quit", command=self._quit_app) menubar.add_cascade(label="File", menu=menu_file) tk.config(menu=menubar) paned = PanedWindow(tk, relief=RAISED) paned.pack(fill=BOTH, expand=1) frame = Frame(paned) paned.add(frame) self._canvas = LayPolyCanvas(frame) bar_x = Scrollbar(frame, orient=HORIZONTAL) bar_x.pack(side=BOTTOM, fill=X) bar_x.config(command=self._canvas.xview) bar_y = Scrollbar(frame, orient=VERTICAL) bar_y.pack(side=RIGHT, fill=Y) bar_y.config(command=self._canvas.yview) self._canvas.config(xscrollcommand=bar_x.set, yscrollcommand=bar_y.set) self._canvas.pack(side=LEFT, expand=True, fill=BOTH) # Thanks to the two guys on Stack Overflow for that! # ( http://stackoverflow.com/a/7734187 ) self._layer_list = Listbox(paned, selectmode=SINGLE) paned.add(self._layer_list) self._scene = None self._current_layer = None self._is_drawing_polygon = False self._tk = tk self._canvas.bind("<Button-1>", self._canvas_left_click) self._canvas.bind("<Button-3>", self._canvas_right_click) self._canvas.bind("<Motion>", self._canvas_mouse_moved) self._layer_list.bind("<<ListboxSelect>>", self._layer_change) self._current_path = None def _canvas_left_click(self, event): if not self._scene or not self._current_layer: return x, y = self._canvas.window_to_canvas_coords(event.x, event.y) if self._is_drawing_polygon: polygon = self._current_layer.get_polygon_at(-1) # Move vtx away from mouse to not interfere with search for closest polygon.get_vertex_at(-1).\ set_coords(x-self.SNAP_RADIUS, y-self.SNAP_RADIUS) closest_vertex = self._current_layer.get_closest_vertex( x, y, self.SNAP_RADIUS) if closest_vertex: polygon.remove_vertex_at(-1) if closest_vertex is polygon.get_vertex_at(0): self._is_drawing_polygon = False else: polygon.add_vertex(closest_vertex) polygon.add_vertex(Vertex(x, y)) else: polygon.get_vertex_at(-1)\ .set_coords(x, y) polygon.add_vertex(Vertex(x, y)) self._canvas.notify_polygon_change(self._current_layer .get_polygon_count()-1) else: # Create start vertex or use already existing one start_vertex = self._current_layer\ .get_closest_vertex(x, y, self.SNAP_RADIUS) if not start_vertex: start_vertex = Vertex(x, y) # Vertex for mouse cursor next_vertex = Vertex(x, y) self._current_layer.add_polygon( Polygon([start_vertex, next_vertex])) self._is_drawing_polygon = True self._canvas.notify_layer_change() def _canvas_right_click(self, event): if not self._current_layer: return if self._is_drawing_polygon: self._current_layer.remove_polygon_at(-1) self._is_drawing_polygon = False else: x, y = self._canvas.window_to_canvas_coords(event.x, event.y) for i in range(0, self._current_layer.get_polygon_count()): if self._current_layer.get_polygon_at(i).contains(x, y): self._current_layer.remove_polygon_at(i) break self._canvas.notify_layer_change() def _canvas_mouse_moved(self, event): if self._is_drawing_polygon: x, y = self._canvas.window_to_canvas_coords(event.x, event.y) self._current_layer.get_polygon_at(-1).get_vertex_at(-1)\ .set_coords(x, y) self._canvas.notify_polygon_change(self._current_layer .get_polygon_count()-1) def _layer_change(self, event): selection = self._layer_list.curselection() if len(selection) > 0 and self._scene: layer = self._scene.get_layer_at(selection[0]) if layer: self._is_drawing_polygon = False self._current_layer = layer self._canvas.notify_new_layer(self._current_layer) def _set_scene(self, scene: Scene) -> bool: if scene.get_layer_count() <= 0: messagebox.showerror("Error!", "Scene has no layers!") return False self._scene = scene # Prepare canvas # TODO Extra 10px padding for canvas width, height = self._scene.get_size() self._canvas.config(scrollregion=(0, 0, width, height)) # Empty listbox, fill it, select first entry self._layer_list.delete(0, self._layer_list.size()-1) for i in range(0, self._scene.get_layer_count()): self._layer_list.insert(i, self._scene.get_layer_at(i).get_name()) self._layer_list.selection_set(0) self._layer_list.event_generate("<<ListboxSelect>>") return True def _set_current_path(self, path): self._current_path = path if path: self._tk.title(path + " - Layered Polygons") else: self._tk.title("Untitled - Layered Polygons") def _new_scene(self): path = filedialog.askopenfilename(defaultextension=".ora", filetypes=[("OpenRaster files", ".ora")]) if not path: return scene = ora.read(path) if not scene: messagebox.showerror("Error!", "File could not be opened!") return if self._set_scene(scene): self._set_current_path(None) def _open_scene(self): path = filedialog.askopenfilename(defaultextension=".lp", filetypes=[("Layered polygons" " files", ".lp")]) if not path: return scene = lp.read(path) if not scene: messagebox.showerror("Error!", "File could not be opened!") return if self._set_scene(scene): self._set_current_path(path) def _save_scene_help(self, path): if lp.save(path, self._scene): self._set_current_path(path) else: messagebox.showerror("Error!", "File could not be saved!") def _save_scene(self): if not self._current_path: self._save_scene_as() return self._save_scene_help(self._current_path) def _save_scene_as(self): if not self._scene: return path = filedialog.asksaveasfilename(defaultextension=".lp", filetypes=[("Layered polygons" " files", ".lp")]) if path: self._save_scene_help(path) def _export_obj(self): if not self._scene: return path_obj = filedialog.asksaveasfilename(defaultextension=".obj", filetypes=[("Wavefront object" " files", ".obj")]) if not path_obj: return path_obj, path_mtl, path_data = obj.get_paths(path_obj) obj.save(path_obj, path_mtl, path_data, self._scene) def _quit_app(self): self._tk.quit() exit()
class ChatGUI(Frame): def __init__(self, parent, conn, title): #Frame.__init__(self, parent, background="grey") self.parent = parent self.conn = conn self.title = title self.centerWindow() self.initUI() def initUI(self): self.lineCounter = 0 # create a custom font self.customFontHeader = font.Font(family="Calibri", slant = "italic") #family="Helvetica", weight="bold", slant="italic") self.customFontMessage = font.Font(family="Calibri") self.parent.title(self.title) frame = Frame(self.parent) frame.pack(fill=BOTH, expand=1, side=LEFT) self.box = ScrolledText(frame, wrap=WORD, relief = GROOVE, width=30, height=18, font=self.customFontMessage) self.box.insert(END, 'Welcome to Python Chat!') self.box.config(state=DISABLED) self.box.pack(expand="yes", fill=BOTH, side=TOP) self.textarea = Text(frame, width=30, height=5) #self.textarea.insert(END, "") self.textarea.bind("<KeyRelease-Return>", self.gettext) #Se metto on press, rimane una newline in piu self.textarea.pack(expand="yes", fill=BOTH, side=TOP) okButton = Button(frame, text="Panic Button", activebackground="red", command=self.sendFile) okButton.pack(expand="no", fill=BOTH, side=TOP) self.usersFrame = Frame(self.parent) self.usersFrame.pack(fill=BOTH, expand=1, side=RIGHT) self.userListbox = Listbox(self.usersFrame, width=3) self.userListbox.bind("<Double-Button-1>", self.privateChat) self.userListbox.pack(fill=BOTH, expand=1) self.updateUsersFrame() def centerWindow(self): w = 600 h = 475 sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() x = (sw - w)/2 y = (sh - h)/2 self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y)) def gettext(self, e): #e sta per event, questo e' un listener text = self.textarea.get("1.0", END + " - 2c") # 1.0: row:columa - END-2c rimuove l'ultimo carattere, una newline \r\n self.textarea.delete("0.0", END) #NON VA: il problema e' che viene inviato il carattere di newline ma non incluso nell'area a causa della bind mi sa. Devo escluderlo io self.sendToServer(text) def printConversation(self, message): self.box.config(state=NORMAL) self.box.insert(END,"\n" + message) self.lineCounter = self.lineCounter + 2 #m = re.match("\[.*\] From .*\n", self.box.get("0.0", END)) m = re.search("\[.*\].*:", message, re.MULTILINE) if m is not None: #print("MATCH") #print(m.group(0)) #print(str(m.start(0)) + "_" + str(m.end(0))) #print("COUNTER") #print(str(self.lineCounter) + "." + str(m.start(0)+1) + "___" + str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_add("header", str(self.lineCounter) + "." + str(m.start(0)), str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_config("header", font=self.customFontHeader, foreground = "blue") self.box.config(state=DISABLED) #self.box.yview_scroll(10000,"units") self.box.see(END) def sendToServer(self, messageToSend): self.conn.send(messageToSend.encode(encoding='utf_8', errors='strict')) def sendFile(self): #aprire una dialog di quelle predefinite (Sfoglia...) #capire come fare la send di un file sul socket... pass def updateUsersFrame(self): global connectedClients self.userListbox.delete(0, END) self.userListbox.insert(END, "Connected users") for item in connectedClients: self.userListbox.insert(END, item) #self.userListbox.update() #self.usersFrame.update() def privateChat(self, e): global conversationBoxList userselected = self.userListbox.selection_get() if not userselected == "Connected users": print("EVVAI CHAT PRIVATA con "+userselected) newWindow = Toplevel(self.parent) newWindow.title("Python Chat with "+userselected) newWindow.minsize(400, 475) newWindow.focus() def disconnectPM(): del conversationBoxList[userselected] newWindow.destroy() newWindow.protocol('WM_DELETE_WINDOW', disconnectPM) #label = Label(newWindow, text="PROVA PROVA") #label.pack(side="top", fill="both", padx=10, pady=10) frame = Frame(newWindow) frame.pack(fill=BOTH, expand=1, side=LEFT) box = ScrolledText(frame, wrap=WORD, relief = GROOVE, width=30, height=18, font=self.customFontMessage) box.config(state=DISABLED) box.pack(expand="yes", fill=BOTH, side=TOP) textarea = Text(frame, width=30, height=5) textarea.bind("<KeyRelease-Return>", lambda event : self.getprivatetext(event, textarea, userselected)) textarea.pack(expand="yes", fill=BOTH, side=TOP) #aggiungo alla mappa globale il box di conversazione conversationBoxList[userselected] = box def receivePrivateChat(self, connectingUser): global conversationBoxList print("CHAT PRIVATA in arrivo con "+connectingUser) newWindow = Toplevel(self.parent) newWindow.title("Python Chat requested by "+connectingUser) newWindow.minsize(400, 475) newWindow.focus() def disconnectPM(): del conversationBoxList[connectingUser] newWindow.destroy() newWindow.protocol('WM_DELETE_WINDOW', disconnectPM) #label = Label(newWindow, text="PROVA PROVA") #label.pack(side="top", fill="both", padx=10, pady=10) frame = Frame(newWindow) frame.pack(fill=BOTH, expand=1, side=LEFT) box = ScrolledText(frame, wrap=WORD, relief = GROOVE, width=30, height=18, font=self.customFontMessage) box.config(state=DISABLED) box.pack(expand="yes", fill=BOTH, side=TOP) textarea = Text(frame, width=30, height=5) textarea.bind("<KeyRelease-Return>", lambda event : self.getprivatetext(event, textarea, connectingUser)) textarea.pack(expand="yes", fill=BOTH, side=TOP) #aggiungo alla mappa globale il box di conversazione conversationBoxList[connectingUser] = box def getprivatetext(self, e, textarea, nickname): text = textarea.get("1.0", END + " - 2c") textarea.delete("0.0", END) self.sendToServer("##" + nickname + "##" + text) def setprivatetext(self, nickname, message, isLocalMessage): #isLocalMessage identifica un messaggio che mando io e che devo ri-ricevere nella mia finestra if isLocalMessage: for i in conversationBoxList.keys(): box = conversationBoxList[i] box.config(state=NORMAL) box.insert(END,"\n" + message) box.config(state=DISABLED) box.see(END) else: conversationbox = conversationBoxList[nickname] conversationbox.config(state=NORMAL) conversationbox.insert(END,"\n" + message) #self.lineCounter = self.lineCounter + 2 #m = re.match("\[.*\] From .*\n", self.box.get("0.0", END)) #m = re.search("\[.*\].*:", message, re.MULTILINE) ''' if m is not None: #print("MATCH") #print(m.group(0)) #print(str(m.start(0)) + "_" + str(m.end(0))) #print("COUNTER") #print(str(self.lineCounter) + "." + str(m.start(0)+1) + "___" + str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_add("header", str(self.lineCounter) + "." + str(m.start(0)), str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_config("header", font=self.customFontHeader, foreground = "blue") ''' conversationbox.config(state=DISABLED) #self.box.yview_scroll(10000,"units") conversationbox.see(END)
class ShiftReduceApp(object): """ A graphical tool for exploring the shift-reduce parser. The tool displays the parser's stack and the remaining text, and allows the user to control the parser's operation. In particular, the user can shift tokens onto the stack, and can perform reductions on the top elements of the stack. A "step" button simply steps through the parsing process, performing the operations that ``nltk.parse.ShiftReduceParser`` would use. """ def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingShiftReduceParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Shift Reduce Parser Application') # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animating_lock = 0 self._animate = IntVar(self._top) self._animate.set(10) # = medium # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Initialize fonts. self._init_fonts(self._top) # Set up key bindings. self._init_bindings() # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # A popup menu for reducing. self._reduce_menu = Menu(self._canvas, tearoff=0) # Reset the demo, and set the feedback frame to empty. self.reset() self._lastoper1['text'] = '' ######################################### ## Initialization Helpers ######################################### def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = tkinter.font.Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = tkinter.font.Font(family='helvetica', weight='bold', size=self._size.get()) self._font = tkinter.font.Font(family='helvetica', size=self._size.get()) def _init_grammar(self, parent): # Grammar view. self._prodframe = listframe = Frame(parent) self._prodframe.pack(fill='both', side='left', padx=2) self._prodlist_label = Label(self._prodframe, font=self._boldfont, text='Available Reductions') self._prodlist_label.pack() self._prodlist = Listbox(self._prodframe, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0') self._prodlist.pack(side='right', fill='both', expand=1) self._productions = list(self._parser.grammar().productions()) for production in self._productions: self._prodlist.insert('end', (' %s' % production)) self._prodlist.config(height=min(len(self._productions), 25)) # Add a scrollbar if there are more than 25 productions. if 1:#len(self._productions) > 25: listscroll = Scrollbar(self._prodframe, orient='vertical') self._prodlist.config(yscrollcommand = listscroll.set) listscroll.config(command=self._prodlist.yview) listscroll.pack(side='left', fill='y') # If they select a production, apply it. self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select) # When they hover over a production, highlight it. self._hover = -1 self._prodlist.bind('<Motion>', self._highlight_hover) self._prodlist.bind('<Leave>', self._clear_hover) def _init_bindings(self): # Quit self._top.bind('<Control-q>', self.destroy) self._top.bind('<Control-x>', self.destroy) self._top.bind('<Alt-q>', self.destroy) self._top.bind('<Alt-x>', self.destroy) # Ops (step, shift, reduce, undo) self._top.bind('<space>', self.step) self._top.bind('<s>', self.shift) self._top.bind('<Alt-s>', self.shift) self._top.bind('<Control-s>', self.shift) self._top.bind('<r>', self.reduce) self._top.bind('<Alt-r>', self.reduce) self._top.bind('<Control-r>', self.reduce) self._top.bind('<Delete>', self.reset) self._top.bind('<u>', self.undo) self._top.bind('<Alt-u>', self.undo) self._top.bind('<Control-u>', self.undo) self._top.bind('<Control-z>', self.undo) self._top.bind('<BackSpace>', self.undo) # Misc self._top.bind('<Control-p>', self.postscript) self._top.bind('<Control-h>', self.help) self._top.bind('<F1>', self.help) self._top.bind('<Control-g>', self.edit_grammar) self._top.bind('<Control-t>', self.edit_sentence) # Animation speed control self._top.bind('-', lambda e,a=self._animate:a.set(20)) self._top.bind('=', lambda e,a=self._animate:a.set(10)) self._top.bind('+', lambda e,a=self._animate:a.set(4)) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill='none', side='bottom') Button(buttonframe, text='Step', background='#90c0d0', foreground='black', command=self.step,).pack(side='left') Button(buttonframe, text='Shift', underline=0, background='#90f090', foreground='black', command=self.shift).pack(side='left') Button(buttonframe, text='Reduce', underline=0, background='#90f090', foreground='black', command=self.reduce).pack(side='left') Button(buttonframe, text='Undo', underline=0, background='#f0a0a0', foreground='black', command=self.undo).pack(side='left') def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Reset Parser', underline=0, command=self.reset, accelerator='Del') filemenu.add_command(label='Print to Postscript', underline=0, command=self.postscript, accelerator='Ctrl-p') filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label='Edit Grammar', underline=5, command=self.edit_grammar, accelerator='Ctrl-g') editmenu.add_command(label='Edit Text', underline=5, command=self.edit_sentence, accelerator='Ctrl-t') menubar.add_cascade(label='Edit', underline=0, menu=editmenu) rulemenu = Menu(menubar, tearoff=0) rulemenu.add_command(label='Step', underline=1, command=self.step, accelerator='Space') rulemenu.add_separator() rulemenu.add_command(label='Shift', underline=0, command=self.shift, accelerator='Ctrl-s') rulemenu.add_command(label='Reduce', underline=0, command=self.reduce, accelerator='Ctrl-r') rulemenu.add_separator() rulemenu.add_command(label='Undo', underline=0, command=self.undo, accelerator='Ctrl-u') menubar.add_cascade(label='Apply', underline=0, menu=rulemenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_checkbutton(label="Show Grammar", underline=0, variable=self._show_grammar, command=self._toggle_grammar) viewmenu.add_separator() viewmenu.add_radiobutton(label='Tiny', variable=self._size, underline=0, value=10, command=self.resize) viewmenu.add_radiobutton(label='Small', variable=self._size, underline=0, value=12, command=self.resize) viewmenu.add_radiobutton(label='Medium', variable=self._size, underline=0, value=14, command=self.resize) viewmenu.add_radiobutton(label='Large', variable=self._size, underline=0, value=18, command=self.resize) viewmenu.add_radiobutton(label='Huge', variable=self._size, underline=0, value=24, command=self.resize) menubar.add_cascade(label='View', underline=0, menu=viewmenu) animatemenu = Menu(menubar, tearoff=0) animatemenu.add_radiobutton(label="No Animation", underline=0, variable=self._animate, value=0) animatemenu.add_radiobutton(label="Slow Animation", underline=0, variable=self._animate, value=20, accelerator='-') animatemenu.add_radiobutton(label="Normal Animation", underline=0, variable=self._animate, value=10, accelerator='=') animatemenu.add_radiobutton(label="Fast Animation", underline=0, variable=self._animate, value=4, accelerator='+') menubar.add_cascade(label="Animate", underline=1, menu=animatemenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label='About', underline=0, command=self.about) helpmenu.add_command(label='Instructions', underline=0, command=self.help, accelerator='F1') menubar.add_cascade(label='Help', underline=0, menu=helpmenu) parent.config(menu=menubar) def _init_feedback(self, parent): self._feedbackframe = feedbackframe = Frame(parent) feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3) self._lastoper_label = Label(feedbackframe, text='Last Operation:', font=self._font) self._lastoper_label.pack(side='left') lastoperframe = Frame(feedbackframe, relief='sunken', border=1) lastoperframe.pack(fill='x', side='right', expand=1, padx=5) self._lastoper1 = Label(lastoperframe, foreground='#007070', background='#f0f0f0', font=self._font) self._lastoper2 = Label(lastoperframe, anchor='w', width=30, foreground='#004040', background='#f0f0f0', font=self._font) self._lastoper1.pack(side='left') self._lastoper2.pack(side='left', fill='x', expand=1) def _init_canvas(self, parent): self._cframe = CanvasFrame(parent, background='white', width=525, closeenough=10, border=2, relief='sunken') self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() self._stackwidgets = [] self._rtextwidgets = [] self._titlebar = canvas.create_rectangle(0,0,0,0, fill='#c0f0f0', outline='black') self._exprline = canvas.create_line(0,0,0,0, dash='.') self._stacktop = canvas.create_line(0,0,0,0, fill='#408080') size = self._size.get()+4 self._stacklabel = TextWidget(canvas, 'Stack', color='#004040', font=self._boldfont) self._rtextlabel = TextWidget(canvas, 'Remaining Text', color='#004040', font=self._boldfont) self._cframe.add_widget(self._stacklabel) self._cframe.add_widget(self._rtextlabel) ######################################### ## Main draw procedure ######################################### def _redraw(self): scrollregion = self._canvas['scrollregion'].split() (cx1, cy1, cx2, cy2) = [int(c) for c in scrollregion] # Delete the old stack & rtext widgets. for stackwidget in self._stackwidgets: self._cframe.destroy_widget(stackwidget) self._stackwidgets = [] for rtextwidget in self._rtextwidgets: self._cframe.destroy_widget(rtextwidget) self._rtextwidgets = [] # Position the titlebar & exprline (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2-y1+10 self._canvas.coords(self._titlebar, -5000, 0, 5000, y-4) self._canvas.coords(self._exprline, 0, y*2-10, 5000, y*2-10) # Position the titlebar labels.. (x1, y1, x2, y2) = self._stacklabel.bbox() self._stacklabel.move(5-x1, 3-y1) (x1, y1, x2, y2) = self._rtextlabel.bbox() self._rtextlabel.move(cx2-x2-5, 3-y1) # Draw the stack. stackx = 5 for tok in self._parser.stack(): if isinstance(tok, Tree): attribs = {'tree_color': '#4080a0', 'tree_width': 2, 'node_font': self._boldfont, 'node_color': '#006060', 'leaf_color': '#006060', 'leaf_font':self._font} widget = tree_to_treesegment(self._canvas, tok, **attribs) widget.label()['color'] = '#000000' else: widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) widget.bind_click(self._popup_reduce) self._stackwidgets.append(widget) self._cframe.add_widget(widget, stackx, y) stackx = widget.bbox()[2] + 10 # Draw the remaining text. rtextwidth = 0 for tok in self._parser.remaining_text(): widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) self._rtextwidgets.append(widget) self._cframe.add_widget(widget, rtextwidth, y) rtextwidth = widget.bbox()[2] + 4 # Allow enough room to shift the next token (for animations) if len(self._rtextwidgets) > 0: stackx += self._rtextwidgets[0].width() # Move the remaining text to the correct location (keep it # right-justified, when possible); and move the remaining text # label, if necessary. stackx = max(stackx, self._stacklabel.width()+25) rlabelwidth = self._rtextlabel.width()+10 if stackx >= cx2-max(rtextwidth, rlabelwidth): cx2 = stackx + max(rtextwidth, rlabelwidth) for rtextwidget in self._rtextwidgets: rtextwidget.move(4+cx2-rtextwidth, 0) self._rtextlabel.move(cx2-self._rtextlabel.bbox()[2]-5, 0) midx = (stackx + cx2-max(rtextwidth, rlabelwidth))/2 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) (x1, y1, x2, y2) = self._stacklabel.bbox() # Set up binding to allow them to shift a token by dragging it. if len(self._rtextwidgets) > 0: def drag_shift(widget, midx=midx, self=self): if widget.bbox()[0] < midx: self.shift() else: self._redraw() self._rtextwidgets[0].bind_drag(drag_shift) self._rtextwidgets[0].bind_click(self.shift) # Draw the stack top. self._highlight_productions() def _draw_stack_top(self, widget): # hack.. midx = widget.bbox()[2]+50 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) def _highlight_productions(self): # Highlight the productions that can be reduced. self._prodlist.selection_clear(0, 'end') for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) ######################################### ## Button Callbacks ######################################### def destroy(self, *e): if self._top is None: return self._top.destroy() self._top = None def reset(self, *e): self._parser.initialize(self._sent) self._lastoper1['text'] = 'Reset App' self._lastoper2['text'] = '' self._redraw() def step(self, *e): if self.reduce(): return True elif self.shift(): return True else: if list(self._parser.parses()): self._lastoper1['text'] = 'Finished:' self._lastoper2['text'] = 'Success' else: self._lastoper1['text'] = 'Finished:' self._lastoper2['text'] = 'Failure' def shift(self, *e): if self._animating_lock: return if self._parser.shift(): tok = self._parser.stack()[-1] self._lastoper1['text'] = 'Shift:' self._lastoper2['text'] = '%r' % tok if self._animate.get(): self._animate_shift() else: self._redraw() return True return False def reduce(self, *e): if self._animating_lock: return production = self._parser.reduce() if production: self._lastoper1['text'] = 'Reduce:' self._lastoper2['text'] = '%s' % production if self._animate.get(): self._animate_reduce() else: self._redraw() return production def undo(self, *e): if self._animating_lock: return if self._parser.undo(): self._redraw() def postscript(self, *e): self._cframe.print_to_file() def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs) ######################################### ## Menubar callbacks ######################################### def resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) #self._stacklabel['font'] = ('helvetica', -size-4, 'bold') #self._rtextlabel['font'] = ('helvetica', -size-4, 'bold') #self._lastoper_label['font'] = ('helvetica', -size) #self._lastoper1['font'] = ('helvetica', -size) #self._lastoper2['font'] = ('helvetica', -size) #self._prodlist['font'] = ('helvetica', -size) #self._prodlist_label['font'] = ('helvetica', -size-2, 'bold') self._redraw() def help(self, *e): # The default font's not very legible; try using 'fixed' instead. try: ShowText(self._top, 'Help: Shift-Reduce Parser Application', (__doc__ or '').strip(), width=75, font='fixed') except: ShowText(self._top, 'Help: Shift-Reduce Parser Application', (__doc__ or '').strip(), width=75) def about(self, *e): ABOUT = ("NLTK Shift-Reduce Parser Application\n"+ "Written by Edward Loper") TITLE = 'About: Shift-Reduce Parser Application' try: from tkinter.messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def edit_grammar(self, *e): CFGEditor(self._top, self._parser.grammar(), self.set_grammar) def set_grammar(self, grammar): self._parser.set_grammar(grammar) self._productions = list(grammar.productions()) self._prodlist.delete(0, 'end') for production in self._productions: self._prodlist.insert('end', (' %s' % production)) def edit_sentence(self, *e): sentence = " ".join(self._sent) title = 'Edit Text' instr = 'Enter a new sentence to parse.' EntryDialog(self._top, sentence, instr, self.set_sentence, title) def set_sentence(self, sent): self._sent = sent.split() #[XX] use tagged? self.reset() ######################################### ## Reduce Production Selection ######################################### def _toggle_grammar(self, *e): if self._show_grammar.get(): self._prodframe.pack(fill='both', side='left', padx=2, after=self._feedbackframe) self._lastoper1['text'] = 'Show Grammar' else: self._prodframe.pack_forget() self._lastoper1['text'] = 'Hide Grammar' self._lastoper2['text'] = '' def _prodlist_select(self, event): selection = self._prodlist.curselection() if len(selection) != 1: return index = int(selection[0]) production = self._parser.reduce(self._productions[index]) if production: self._lastoper1['text'] = 'Reduce:' self._lastoper2['text'] = '%s' % production if self._animate.get(): self._animate_reduce() else: self._redraw() else: # Reset the production selections. self._prodlist.selection_clear(0, 'end') for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) def _popup_reduce(self, widget): # Remove old commands. productions = self._parser.reducible_productions() if len(productions) == 0: return self._reduce_menu.delete(0, 'end') for production in productions: self._reduce_menu.add_command(label=str(production), command=self.reduce) self._reduce_menu.post(self._canvas.winfo_pointerx(), self._canvas.winfo_pointery()) ######################################### ## Animations ######################################### def _animate_shift(self): # What widget are we shifting? widget = self._rtextwidgets[0] # Where are we shifting from & to? right = widget.bbox()[0] if len(self._stackwidgets) == 0: left = 5 else: left = self._stackwidgets[-1].bbox()[2]+10 # Start animating. dt = self._animate.get() dx = (left-right)*1.0/dt self._animate_shift_frame(dt, widget, dx) def _animate_shift_frame(self, frame, widget, dx): if frame > 0: self._animating_lock = 1 widget.move(dx, 0) self._top.after(10, self._animate_shift_frame, frame-1, widget, dx) else: # but: stacktop?? # Shift the widget to the stack. del self._rtextwidgets[0] self._stackwidgets.append(widget) self._animating_lock = 0 # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() def _animate_reduce(self): # What widgets are we shifting? numwidgets = len(self._parser.stack()[-1]) # number of children widgets = self._stackwidgets[-numwidgets:] # How far are we moving? if isinstance(widgets[0], TreeSegmentWidget): ydist = 15 + widgets[0].label().height() else: ydist = 15 + widgets[0].height() # Start animating. dt = self._animate.get() dy = ydist*2.0/dt self._animate_reduce_frame(dt/2, widgets, dy) def _animate_reduce_frame(self, frame, widgets, dy): if frame > 0: self._animating_lock = 1 for widget in widgets: widget.move(0, dy) self._top.after(10, self._animate_reduce_frame, frame-1, widgets, dy) else: del self._stackwidgets[-len(widgets):] for widget in widgets: self._cframe.remove_widget(widget) tok = self._parser.stack()[-1] if not isinstance(tok, Tree): raise ValueError() label = TextWidget(self._canvas, str(tok.label()), color='#006060', font=self._boldfont) widget = TreeSegmentWidget(self._canvas, label, widgets, width=2) (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2-y1+10 if not self._stackwidgets: x = 5 else: x = self._stackwidgets[-1].bbox()[2] + 10 self._cframe.add_widget(widget, x, y) self._stackwidgets.append(widget) # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() # # Delete the old widgets.. # del self._stackwidgets[-len(widgets):] # for widget in widgets: # self._cframe.destroy_widget(widget) # # # Make a new one. # tok = self._parser.stack()[-1] # if isinstance(tok, Tree): # attribs = {'tree_color': '#4080a0', 'tree_width': 2, # 'node_font': bold, 'node_color': '#006060', # 'leaf_color': '#006060', 'leaf_font':self._font} # widget = tree_to_treesegment(self._canvas, tok.type(), # **attribs) # widget.node()['color'] = '#000000' # else: # widget = TextWidget(self._canvas, tok.type(), # color='#000000', font=self._font) # widget.bind_click(self._popup_reduce) # (x1, y1, x2, y2) = self._stacklabel.bbox() # y = y2-y1+10 # if not self._stackwidgets: x = 5 # else: x = self._stackwidgets[-1].bbox()[2] + 10 # self._cframe.add_widget(widget, x, y) # self._stackwidgets.append(widget) #self._redraw() self._animating_lock = 0 ######################################### ## Hovering. ######################################### def _highlight_hover(self, event): # What production are we hovering over? index = self._prodlist.nearest(event.y) if self._hover == index: return # Clear any previous hover highlighting. self._clear_hover() # If the production corresponds to an available reduction, # highlight the stack. selection = [int(s) for s in self._prodlist.curselection()] if index in selection: rhslen = len(self._productions[index].rhs()) for stackwidget in self._stackwidgets[-rhslen:]: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()['color'] = '#00a000' else: stackwidget['color'] = '#00a000' # Remember what production we're hovering over. self._hover = index def _clear_hover(self, *event): # Clear any previous hover highlighting. if self._hover == -1: return self._hover = -1 for stackwidget in self._stackwidgets: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()['color'] = 'black' else: stackwidget['color'] = 'black'
class LogUI(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.filemodels = [] filemodel1 = FileModel("C:/Users/chen_xi/test1.csv", searchconds=[], relation="and", joincondtuples=[]) filemodel2 = FileModel("C:/Users/chen_xi/test2.csv", searchconds=[], relation="and", joincondtuples=[]) self.filemodels = [filemodel1, filemodel2] self._initUI() self.selectedfileindex = -1 def _initUI(self): self.parent.title("Log Processor") self.pack() self._initfilepanel() self._initsearchcondpanel() self._initjoincondpanel() self._initconsole() self._inflatefilelist() def _initfilepanel(self): frame = Frame(self) frame.grid(row=0, column=0, sticky=E + W + S + N) label = Label(frame, text="File List: ") label.grid(sticky=N + W) self.filelist = Listbox(frame, width=40) self.filelist.grid(row=1, column=0, rowspan=2, columnspan=3) vsl = Scrollbar(frame, orient=VERTICAL) vsl.grid(row=1, column=3, rowspan=2, sticky=N + S + W) hsl = Scrollbar(frame, orient=HORIZONTAL) hsl.grid(row=3, column=0, columnspan=3, sticky=W + E + N) self.filelist.config(yscrollcommand=vsl.set, xscrollcommand=hsl.set) self.filelist.bind('<<ListboxSelect>>', self._onfilelistselection) hsl.config(command=self.filelist.xview) vsl.config(command=self.filelist.yview) upbtn = Button(frame, text="Up", width=7, command=self._upfile) upbtn.grid(row=1, column=4, padx=5, pady=5) downbtn = Button(frame, text="Down", width=7, command=self._downfile) downbtn.grid(row=2, column=4, padx=5, pady=5) newbtn = Button(frame, text="New", width=7, command=self._addfile) newbtn.grid(row=4, column=1, pady=5, sticky=E + S) delbtn = Button(frame, text="Delete", width=7, command=self._deletefile) delbtn.grid(row=4, column=2, padx=5, pady=5, sticky=W + S) def _inflatefilelist(self): self.filelist.delete(0, END) for filemodel in self.filemodels: self.filelist.insert(END, filemodel.filename) def _initsearchcondpanel(self): frame = Frame(self) frame.grid(row=0, column=1, sticky=E + W + S + N, padx=5) label = Label(frame, text="Search Condition: ") label.grid(row=0, column=0, columnspan=1, sticky=W) relationlable = Label(frame, text="Relation") relationlable.grid(row=0, column=1, columnspan=1, sticky=E) self.condrelationvar = StringVar(frame) relationinput = Combobox(frame, textvariable=self.condrelationvar, values=["and", "or"]) relationinput.grid(row=0, column=2, padx=5, sticky=E) relationinput.bind('<<ComboboxSelected>>', self._onrelationchange) self.searchcondlist = Listbox(frame) self.searchcondlist.grid(row=1, rowspan=1, columnspan=3, sticky=E + W + S + N) vsl = Scrollbar(frame, orient=VERTICAL) vsl.grid(row=1, column=3, rowspan=1, sticky=N + S + W) hsl = Scrollbar(frame, orient=HORIZONTAL) hsl.grid(row=2, column=0, columnspan=3, sticky=W + E + N) self.searchcondlist.config(yscrollcommand=vsl.set, xscrollcommand=hsl.set) hsl.config(command=self.searchcondlist.xview) vsl.config(command=self.searchcondlist.yview) newbtn = Button(frame, text="New", width=7, command=self._addsearchcondition) newbtn.grid(row=3, column=0, padx=5, pady=5, sticky=E) delbtn = Button(frame, text="Delete", width=7, command=self._deletesearchcondition) delbtn.grid(row=3, column=1, sticky=E) modbtn = Button(frame, text="Update", width=7, command=self._modifysearchcondition) modbtn.grid(row=3, column=2, padx=5, pady=5, sticky=W) def _onrelationchange(self, evt): selectedmodel = self._getselectedfile() selectedmodel.relation = self.condrelationvar.get() def _inflatesearchcondlist(self, filemodel): self.condrelationvar.set(filemodel.relation) conds = filemodel.searchconds self.searchcondlist.delete(0, END) for cond in conds: self.searchcondlist.insert(END, cond.tostring()) def _initjoincondpanel(self): frame = Frame(self) frame.grid(row=0, column=2, sticky=E + W + S + N, padx=5) label = Label(frame, text="Join Condition: ") label.grid(sticky=N + W) self.joincondlist = Listbox(frame) self.joincondlist.grid(row=1, rowspan=1, columnspan=3, sticky=E + W + S + N) vsl = Scrollbar(frame, orient=VERTICAL) vsl.grid(row=1, column=3, rowspan=1, sticky=N + S + W) hsl = Scrollbar(frame, orient=HORIZONTAL) hsl.grid(row=2, column=0, columnspan=3, sticky=W + E + N) self.joincondlist.config(yscrollcommand=vsl.set, xscrollcommand=hsl.set) hsl.config(command=self.joincondlist.xview) vsl.config(command=self.joincondlist.yview) newbtn = Button(frame, text="New", width=7, command=self._addjoincondition) newbtn.grid(row=3, column=0, padx=5, pady=5, sticky=E) delbtn = Button(frame, text="Delete", width=7, command=self._deletejoincondition) delbtn.grid(row=3, column=1, sticky=E) modbtn = Button(frame, text="Update", width=7, command=self._modifyjoincondition) modbtn.grid(row=3, column=2, padx=5, pady=5, sticky=W) def _inflatejoincondlist(self, condtuples): self.joincondlist.delete(0, END) for condtuple in condtuples: cond = condtuple[0] tofilename = condtuple[1] self.joincondlist.insert(END, cond.tostring() + " in " + tofilename) def _initconsole(self): separator = Separator(self, orient=HORIZONTAL) separator.grid(row=1, columnspan=3, sticky=W + E, padx=5, pady=5) self.console = Text(self) self.console.grid(row=2, columnspan=3, sticky=W + E, padx=5, pady=5) vsl = Scrollbar(self, orient=VERTICAL) vsl.grid(row=2, column=3, sticky=N + S + W) hsl = Scrollbar(self, orient=HORIZONTAL) hsl.grid(row=3, column=0, columnspan=3, sticky=W + E + N) hsl.config(command=self.console.xview) vsl.config(command=self.console.yview) resbtn = Button(self, text="Search", width=7, comman=self._showsearchresult) resbtn.grid(row=4, column=2, padx=5, pady=5, sticky=E) def _showsearchresult(self): try: res = self._searchresult() formatres = self._formatsearchresult(res) except Exception: formatres = "Error!\r\n" + traceback.format_exc() self.console.delete("0.0", END) self.console.insert("0.0", formatres) def _searchresult(self): filesearchs = [] joinsearchs = [] for filemodel in self.filemodels: filename = filemodel.filename singlesearch = SingleFileSearch(filename, DictReader(open(filename)), filemodel.searchconds, filemodel.relation) filesearchs.append(singlesearch) joindict = {} for joincondtuple in filemodel.joincondtuples: tofilename = joincondtuple[1] joincond = joincondtuple[0] if tofilename not in joindict: joindict[tofilename] = [] joindict[tofilename].append(joincond) for tofilename in joindict: joinsearch = JoinFileSearch(filename, DictReader(open(filename)), tofilename, DictReader(open(tofilename)), joindict[tofilename]) joinsearchs.append(joinsearch) search = Search(filesearchs, joinsearchs) return search.process() def _formatsearchresult(self, searchresult): formatres = self._formatsummary(searchresult) + "\r\n" fileresults = searchresult.results for filemodel in self.filemodels: filename = filemodel.filename fileresult = fileresults[filename] formatres += self._formatfileresult(fileresult) formatres += "\r\n" return formatres def _formatsummary(self, searchresult): res = "Summary\r\n" res += "Time Cost: " + str(searchresult.timecost) + " Seconds\r\n" fileresults = searchresult.results for filemodel in self.filemodels: filename = filemodel.filename fileresult = fileresults[filename] res += filename + " Size: " + str(len(fileresult.result)) + "\r\n" return res def _formatfileresult(self, fileresult): res = "" filename = fileresult.filename res += filename + " Size: " + str(len(fileresult.result)) + "\r\n" fields = csvhandler.getfields(filename) for (i, field) in enumerate(fields): res += field if i < (len(fields) - 1): res += "," else: res += "\r\n" for rowdict in fileresult.result: for (i, field) in enumerate(fields): res += rowdict[field] if i < (len(fields) - 1): res += "," else: res += "\r\n" return res def _addfile(self): filetypes = [('csv files', '*.csv'), ('All files', '*')] selectedfile = askopenfilename(filetypes=filetypes) if selectedfile is not None: newmodel = FileModel(selectedfile, searchconds=[], relation="and", joincondtuples=[]) self.filemodels.append(newmodel) self.filelist.insert(END, newmodel.filename) self._setselectedfileindex(len(self.filemodels) - 1) def _deletefile(self): index = self._getselectedfileindex() if index >= 0: self.filelist.delete(index) del self.filemodels[index] self._setselectedfileindex(-1) def _upfile(self): if self._getselectedfileindex() <= 0: return index = self._getselectedfileindex() selectedfilename = self._getselectedfile().filename if index > 0: self.filelist.insert((index - 1), selectedfilename) self.filelist.delete(index + 1) self.filemodels[index - 1], self.filemodels[index] = self.filemodels[index], self.filemodels[index - 1] self._setselectedfileindex(index - 1) def _downfile(self): if self._getselectedfileindex() < 0: return index = self._getselectedfileindex() selectedfilename = self._getselectedfile().filename if index < (len(self.filemodels) - 1): self.filelist.insert((index + 2), selectedfilename) self.filelist.delete(index) self.filemodels[index], self.filemodels[index + 1] = self.filemodels[index + 1], self.filemodels[index] self._setselectedfileindex(index + 1) def _onfilelistselection(self, evt): if len(self.filelist.curselection()) == 0: return self._setselectedfileindex(self.filelist.curselection()[0]) selectedfile = self._getselectedfile() self._inflatesearchcondlist(selectedfile) joincondtuples = selectedfile.joincondtuples self._inflatejoincondlist(joincondtuples) def _addsearchcondition(self): if self._getselectedfileindex() < 0: return self._popupsearchcondwindow() def _deletesearchcondition(self): index = self._getselectedsearchcondindex() if index < 0: return selectedfile = self._getselectedfile() del selectedfile.searchconds[index] self.searchcondlist.delete(index) def _modifysearchcondition(self): if self._getselectedsearchcondindex() < 0: return self._popupsearchcondwindow(self._getselectedsearchcondindex()) def _addjoincondition(self): if self._getselectedfileindex() < 0: return self._popupjoincondwindow() def _deletejoincondition(self): index = self._getselectedjoincondindex() if index < 0: return selectedfile = self._getselectedfile() del selectedfile.joincondtuples[index] self.joincondlist.delete(index) def _modifyjoincondition(self): if self._getselectedjoincondindex() < 0: return self._popupjoincondwindow(self._getselectedjoincondindex()) def _popupsearchcondwindow(self, index=-1): if index < 0: cond = ValueSearchCondition("", "") else: cond = self._getselectedfile().searchconds[index] window = Toplevel(self) title = Label(window, text="New Search Condition") title.grid(row=0, column=0, padx=5, pady=5, sticky=W + N) fieldlabel = Label(window, text="Field Name: ") fieldlabel.grid(row=1, column=0, padx=5, pady=5, sticky=W) fields = csvhandler.getfields(self._getselectedfile().filename) fieldvar = StringVar(window) fieldinput = Combobox(window, textvariable=fieldvar, values=fields, width=20) fieldinput.grid(row=1, column=1, columnspan=2, padx=5, pady=5, sticky=W) valuelabel = Label(window, text="Value: ") valuelabel.grid(row=3, column=0, padx=5, pady=5, sticky=W) valueinput = Entry(window) valueinput.grid(row=3, column=1, columnspan=2, padx=5, pady=5, sticky=W) minlabel = Label(window, text="Min Value: ") minlabel.grid(row=4, column=0, padx=5, pady=5, sticky=W) mininput = Entry(window) mininput.grid(row=4, column=1, columnspan=2, padx=5, pady=5, sticky=W) maxlabel = Label(window, text="Max Value: ") maxlabel.grid(row=5, column=0, padx=5, pady=5, sticky=W) maxinput = Entry(window) maxinput.grid(row=5, column=1, columnspan=2, padx=5, pady=5, sticky=W) sarchkind = IntVar() def _enablesingle(): valueinput.config(state=NORMAL) mininput.config(state=DISABLED) maxinput.config(state=DISABLED) singlebutton.select() def _enablejoin(): valueinput.config(state=DISABLED) mininput.config(state=NORMAL) maxinput.config(state=NORMAL) joinbutton.select() typelabel = Label(window, text="Search Type: ") typelabel.grid(row=2, column=0, padx=5, pady=5, sticky=W) singlebutton = Radiobutton(window, text="Single", variable=sarchkind, value=1, command=_enablesingle) singlebutton.grid(row=2, column=1, columnspan=1, padx=5, pady=5, sticky=W) joinbutton = Radiobutton(window, text="Range", variable=sarchkind, value=2, command=_enablejoin) joinbutton.grid(row=2, column=2, columnspan=1, padx=5, pady=5, sticky=W) # init value fieldvar.set(cond.field) if isinstance(cond, ValueSearchCondition): valueinput.insert(0, cond.val) _enablesingle() elif isinstance(cond, RangeSearchCondition): mininput.insert(0, cond.valmin) maxinput.insert(0, cond.valmax) _enablejoin() def _newcond(): '''create new condition ''' if sarchkind.get() == 1: cond = ValueSearchCondition(fieldvar.get(), valueinput.get()) else: cond = RangeSearchCondition(fieldvar.get(), mininput.get(), maxinput.get()) selectedfile = self._getselectedfile() if index < 0: selectedfile.searchconds.append(cond) else: del selectedfile.searchconds[index] selectedfile.searchconds[index:index] = [cond] self._inflatesearchcondlist(selectedfile) window.destroy() okbtn = Button(window, text="Confirm", width=7, command=_newcond) okbtn.grid(row=6, column=1, rowspan=1, columnspan=1, sticky=E, padx=5, pady=5) clsbtn = Button(window, text="Close", width=7, command=lambda: window.destroy()) clsbtn.grid(row=6, column=2, rowspan=1, columnspan=1, sticky=E, padx=5, pady=5) def _popupjoincondwindow(self, index=-1): if index < 0: cond = JoinSearchCondition(("", "")) tofilename = "" else: condtuple = self._getselectedfile().joincondtuples[index] cond = condtuple[0] tofilename = condtuple[1] window = Toplevel(self) title = Label(window, text="New Search Condition") title.grid(row=0, column=0, padx=5, pady=5, sticky=W + N) filenamelabel = Label(window, text="Target Field Name: ") filenamelabel.grid(row=1, column=0, padx=5, pady=5, sticky=W) filevar = StringVar(window) filenameinput = Combobox(window, textvariable=filevar, values=self.filelist.get(0, END), width=30) filenameinput.grid(row=1, column=1, columnspan=2, padx=5, pady=5, sticky=W) fromfieldlabel = Label(window, text="Field in From File: ") fromfieldlabel.grid(row=3, column=0, padx=5, pady=5, sticky=W) fromfields = csvhandler.getfields(self._getselectedfile().filename) fromfieldvar = StringVar(window) fieldinput = Combobox(window, textvariable=fromfieldvar, values=fromfields, width=20) fieldinput.grid(row=3, column=1, columnspan=2, padx=5, pady=5, sticky=W) tofieldlabel = Label(window, text="Field in Target File: ") tofieldlabel.grid(row=4, column=0, padx=5, pady=5, sticky=W) tofields = [] tofieldvar = StringVar(window) tofieldinput = Combobox(window, textvariable=tofieldvar, values=tofields, width=20) tofieldinput.grid(row=4, column=1, columnspan=2, padx=5, pady=5, sticky=W) def updatetofieldinput(evt): if filevar.get() is not None and len(filevar.get()) > 0: tofields = csvhandler.getfields(filevar.get()) window.grid_slaves(4, 1)[0].grid_forget() tofieldinput = Combobox(window, textvariable=tofieldvar, values=tofields, width=20) tofieldinput.grid(row=4, column=1, columnspan=2, padx=5, pady=5, sticky=W) filenameinput.bind('<<ComboboxSelected>>', updatetofieldinput) # init value filevar.set(tofilename) fromfieldvar.set(cond.fieldtuple[0]) updatetofieldinput(None) tofieldvar.set(cond.fieldtuple[1]) def _newcond(): '''create new condition ''' cond = JoinSearchCondition((fromfieldvar.get(), tofieldvar.get())) tofilename = filevar.get() selectedfile = self._getselectedfile() if index < 0: selectedfile.joincondtuples.append((cond, tofilename)) else: del selectedfile.joincondtuples[index] selectedfile.joincondtuples[index:index] = [(cond, tofilename)] self._inflatejoincondlist(selectedfile.joincondtuples) window.destroy() okbtn = Button(window, text="Confirm", width=7, command=_newcond) okbtn.grid(row=6, column=1, rowspan=1, columnspan=1, sticky=E, padx=5, pady=5) clsbtn = Button(window, text="Close", width=7, command=lambda: window.destroy()) clsbtn.grid(row=6, column=2, rowspan=1, columnspan=1, sticky=W, padx=5, pady=5) def _getselectedfile(self): if self._getselectedfileindex() < 0: return None return self.filemodels[self._getselectedfileindex()] def _getselectedfileindex(self): return self.selectedfileindex def _setselectedfileindex(self, index): self.selectedfileindex = index if index >= 0: self.filelist.selection_set(index) def _getselectedsearchcondindex(self): if len(self.searchcondlist.curselection()) > 0: return self.searchcondlist.curselection()[0] return -1 def _getselectedjoincondindex(self): if len(self.joincondlist.curselection()) > 0: return self.joincondlist.curselection()[0] return -1
class FilePane: def __init__(self, root, items=list(), on_selection=list(), on_close=list()): self.items = items self.item_count = len(items) self.on_selection = on_selection self.on_close = on_close self.window = Toplevel() self.window.title('Files') self.window.transient(root) self.window.protocol("WM_DELETE_WINDOW", self.on_window_close) self.menubar = Menu(self.window) self.menubar.add_command(label='Previous', command=self.previous) self.menubar.add_command(label='Next', command=self.next) # Display the menu self.window.config(menu=self.menubar) self.scrollbar = Scrollbar(self.window, orient='vertical') self.listbox = Listbox(self.window, yscrollcommand=self.scrollbar.set, exportselection=False) self.set_items(items) self.scrollbar.config(command=self.listbox.yview) self.scrollbar.pack(side='right', fill='y') self.listbox.pack(side='left', fill='both', expand=1) self.listbox.bind('<<ListboxSelect>>', self.on_select) def on_window_close(self): for callback in self.on_close: callback() self.window.withdraw() def hide(self): self.window.withdraw() def show(self): self.window.deiconify() def selected_item(self): return self.items[self.listbox.curselection()[0]] def select_index(self, index): self.listbox.selection_clear(0, END) # From https://stackoverflow.com/a/25451279/11628429 self.listbox.select_set( index) #This only sets focus on the first item. self.listbox.event_generate("<<ListboxSelect>>") def set_items(self, items): self.items = items self.item_count = len(items) self.listbox.delete(0, END) for item in items: item = path.split(item)[1] self.listbox.insert(END, item) self.select_index(0) def previous(self): index = self.listbox.curselection()[0] - 1 if index < 0: index = self.item_count - 1 self.select_index(index) def next(self): index = self.listbox.curselection()[0] + 1 if index >= self.item_count: index = 0 self.select_index(index) def on_select(self, event): if self.on_selection: for callback in self.on_selection: callback(self.selected_item())
class GUI(Frame): # pylint: disable=too-many-ancestors """class for GUI""" static_logger = logging.getLogger(__name__) static_queue = queue.Queue() def __init__(self, parent, db, pab, alg): """init""" Frame.__init__(self, parent) self.right_list = Listbox(parent) self.left_list = Listbox(parent) self.parent = parent self.db_creator = db self.path_and_bag = pab self.alg_do = alg self.menu_bar = Menu(self.parent) self.init_ui() def init_ui(self): """getting all things started""" self.parent.title("PyMeno") self.left_list.bind("<Double-Button-1>", self.on_double_click) self.parent.config(menu=self.menu_bar) file_menu = Menu(self.menu_bar, tearoff=False) menu2_parse = Menu(self.menu_bar, tearoff=False) # menu3_parse = Menu(menu_bar, tearoff=False) # sub_menu = Menu(file_menu, tearoff=False) self.left_list.pack(side=LEFT, fill=BOTH, expand=2) self.right_list.pack(side=RIGHT, fill=BOTH, expand=2) # add something to menu file_menu.add_command(label="Choose folder with music ALG 1", underline=0, command=self.new_thread_2) file_menu.add_command(label="Choose folder with music ALG 2", underline=0, command=self.new_thread_1) file_menu.add_command(label="Choose folder with music ALG 3", underline=0, command=self.new_thread_2) file_menu.add_command(label="Exit", underline=0, command=self.on_exit) menu2_parse.add_command(label="Download artists list", underline=0, command=self.db_creator.download_list_of_artists) menu2_parse.\ add_command(label="Parse artists information to database", underline=0, command=self.go_to_lilis_parsing) self.menu_bar.add_cascade(label="File", underline=0, menu=file_menu) self.menu_bar.add_cascade(label="Data", underline=0, menu=menu2_parse) def on_exit(self): """quit""" GUI.static_queue.put("endino-tarantino") self.quit() def disable_menu(self): """disable menu while program is working""" self.menu_bar.entryconfig("File", state="disabled") self.menu_bar.entryconfig("Data", state="disabled") def enable_menu(self): """enable menu after work""" self.menu_bar.entryconfig("File", state="normal") self.menu_bar.entryconfig("Data", state="normal") def new_thread_1(self): """thread for the first algorythm""" dir_name = filedialog.askdirectory(parent=self, initialdir="/", title='Please select a directory') if dir_name != "": self.disable_menu() self.path_and_bag.check_if_refresh(dir_name) self.config(cursor="wait") self.update() self.clean_queue() GUI.static_queue.put("Finding files in chosen folder:\n\n") num_files = len([val for sub_list in [[os.path.join(i[0], j)for j in i[2]] for i in os.walk(dir_name)] for val in sub_list]) rott = tk.Tk() app = App(rott, GUI.static_queue, num_files) rott.protocol("WM_DELETE_WINDOW", app.on_closing) thread = threading.Thread(target=self.open_menu, args=(dir_name,)) thread.setDaemon(True) thread.start() app.mainloop() else: print("Action aborted") def open_menu(self, dir_name): """select directory with music, alg 1""" list_of_songs = [] self.path_and_bag.clear_bag_of_words() for data in os.walk(dir_name): for filename in data[2]: list_of_songs = self.path_and_bag.change_title(os.path.join(data[0], filename)) GUI.static_queue.put(filename) if not list_of_songs: print("action aborted") else: GUI.static_queue.put("\nAnd what we have here?:\n") self.config(cursor="") shared_items_add = self.alg_do.search_for_simmilar_ver_2(False, GUI.static_queue) if not shared_items_add: shared_items_add = self.alg_do.search_for_simmilar_ver_2(True, GUI.static_queue) if shared_items_add: self.left_list.delete(0, END) self.right_list.delete(0, END) for song in list_of_songs: temp = song.split(',', 1) self.insert_to_right_list_box(temp[0], temp[1]) for key, value in shared_items_add.items(): temp = key.split(',', 1) GUI.static_queue.put(temp[0] + " : " + value) self.insert_to_left_list_box(temp[0] + " : " + value) GUI.static_queue.put("endino-tarantino") self.enable_menu() def new_thread_2(self): """thread for the second algorythm""" dir_name = filedialog.askdirectory(parent=self, initialdir="/", title='Please select a directory') if dir_name != "": self.disable_menu() self.path_and_bag.check_if_refresh(dir_name) self.config(cursor="wait") self.update() self.clean_queue() GUI.static_queue.put("Finding files in chosen folder:\n\n") num_files = len([val for sub_list in [[os.path.join(i[0], j)for j in i[2]] for i in os.walk(dir_name)] for val in sub_list]) rott = tk.Tk() app = App(rott, GUI.static_queue, num_files) rott.protocol("WM_DELETE_WINDOW", app.on_closing) thread = threading.Thread(target=self.open_menu_ver_2, args=(dir_name,)) thread.setDaemon(True) thread.start() app.mainloop() else: print("Action aborted") @staticmethod def clean_queue(): """cleaning queue if user exit manualy""" if not GUI.static_queue.empty(): while not GUI.static_queue.empty(): GUI.static_queue.get() def open_menu_ver_2(self, dir_name): """select directory with music, alg 2""" list_of_songs = [] self.path_and_bag.clear_bag_of_words() for data in os.walk(dir_name): for filename in data[2]: list_of_songs = self.path_and_bag.change_title(os.path.join(data[0], filename)) GUI.static_queue.put(filename) if not list_of_songs: print("action aborted") else: GUI.static_queue.put("\nAnd what we have here?:\n") self.config(cursor="") shared_items_add = self.alg_do.search_for_simmilar_ver_1(False, GUI.static_queue) if not shared_items_add: shared_items_add = self.alg_do.search_for_simmilar_ver_1(True, GUI.static_queue) if shared_items_add: self.left_list.delete(0, END) self.right_list.delete(0, END) for song in list_of_songs: temp = song.split(',', 1) self.insert_to_right_list_box(temp[0], temp[1]) for key, value in shared_items_add.items(): temp = key.split(',', 1) self.insert_to_left_list_box(temp[0] + " : " + value) GUI.static_queue.put("endino-tarantino") self.enable_menu() def new_thread_3(self): """thread for the third algorythm""" dir_name = filedialog.askdirectory(parent=self, initialdir="/", title='Please select a directory') if dir_name != "": self.disable_menu() self.path_and_bag.check_if_refresh(dir_name) self.config(cursor="wait") self.update() self.clean_queue() GUI.static_queue.put("Finding files in chosen folder:\n\n") num_files = len([val for sub_list in [[os.path.join(i[0], j) for j in i[2]] for i in os.walk(dir_name)] for val in sub_list]) rott = tk.Tk() app = App(rott, GUI.static_queue, num_files) rott.protocol("WM_DELETE_WINDOW", app.on_closing) thread = threading.Thread(target=self.open_menu_ver_3, args=(dir_name,)) thread.setDaemon(True) thread.start() app.mainloop() else: print("Action aborted") def open_menu_ver_3(self, dir_name): """select directory with music, alg 3""" list_of_songs = [] self.path_and_bag.clear_bag_of_words() for data in os.walk(dir_name): for filename in data[2]: list_of_songs = self.path_and_bag.change_title(os.path.join(data[0], filename)) GUI.static_queue.put(filename) print(list_of_songs) if not list_of_songs: print("action aborted") else: GUI.static_queue.put("\nAnd what we have here?:\n") self.config(cursor="") shared_items_add = self.alg_do.search_for_simmilar_ver_3(False, GUI.static_queue) if not shared_items_add: shared_items_add = self.alg_do.search_for_simmilar_ver_3(True, GUI.static_queue) if shared_items_add: self.left_list.delete(0, END) self.right_list.delete(0, END) for song in list_of_songs: temp = song.split(',', 1) self.insert_to_right_list_box(temp[0], temp[1]) for key, value in shared_items_add.items(): temp = key.split(',', 1) self.insert_to_left_list_box(temp[0] + " : " + value) GUI.static_queue.put("endino-tarantino") self.enable_menu() def insert_to_right_list_box(self, artist, song): """insert to right listbox for other methods""" self.right_list.insert(END, artist + " - " + song) def insert_to_left_list_box(self, artist): """insert to left listbox for other methods""" self.left_list.insert(END, artist) def go_to_lilis_parsing(self): """how many artist do you want to parse""" number_from = simpledialog.askstring('Number', 'How many artists?/FROM') if number_from is not None: number_from = int(number_from) print(number_from) number_to = int(simpledialog.askstring('Number', 'How many artists?/TO')) if number_to is not None: number_to = int(number_to) print(number_to) self.db_creator.parse_file(number_to, number_from) def on_double_click(self, event): """open youtube on double click""" new = 2 # open in a new tab, if possible widget = event.widget selection = widget.curselection() value = widget.get(selection[0]) url = self.youtube_search(value) webbrowser.open(url, new=new) @staticmethod def youtube_search(to_search): """ This function finds url to our songs throw Youtube API """ developer_key = "AIzaSyCn9Pk4vWC8LjjIKqol5gkku20DI0IRurU" youtube_api_service_name = "youtube" youtube_api_version = "v3" parse = argparse.ArgumentParser() parse.add_argument("--q", help="Search term", default=to_search) parse.add_argument("--max-results", help="Max results", default=25) args = parse.parse_args() youtube = build(youtube_api_service_name, youtube_api_version, developerKey=developer_key) # Call the search.list method to retrieve results matching the specified # query term. search_response = youtube.search().list(q=args.q, # pylint: disable=no-member part="id,snippet", maxResults=args.max_results, order="viewCount").execute() videos = [] channels = [] play_lists = [] # Add each result to the appropriate list, and then display the lists of # matching videos, channels, and play lists. for search_result in search_response.get("items", []): if search_result["id"]["kind"] == "youtube#video": videos.append(search_result["id"]["videoId"]) elif search_result["id"]["kind"] == "youtube#channel": channels.append("%s (%s)" % (search_result["snippet"]["title"], search_result["id"]["channelId"])) elif search_result["id"]["kind"] == "youtube#playlist": play_lists.append("%s (%s)" % (search_result["snippet"]["title"], search_result["id"]["playlistId"])) try: return "https://www.youtube.com/watch?v=" + videos[0] except (UnicodeEncodeError, IndexError): GUI.static_logger.error('ERROR', exc_info=True) return "https://www.youtube.com/watch?v=" + "_NXrTujMP50"
class ShiftReduceApp(object): """ A graphical tool for exploring the shift-reduce parser. The tool displays the parser's stack and the remaining text, and allows the user to control the parser's operation. In particular, the user can shift tokens onto the stack, and can perform reductions on the top elements of the stack. A "step" button simply steps through the parsing process, performing the operations that ``nltk.parse.ShiftReduceParser`` would use. """ def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingShiftReduceParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Shift Reduce Parser Application') # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animating_lock = 0 self._animate = IntVar(self._top) self._animate.set(10) # = medium # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Initialize fonts. self._init_fonts(self._top) # Set up key bindings. self._init_bindings() # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # A popup menu for reducing. self._reduce_menu = Menu(self._canvas, tearoff=0) # Reset the demo, and set the feedback frame to empty. self.reset() self._lastoper1['text'] = '' ######################################### ## Initialization Helpers ######################################### def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = tkinter.font.Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = tkinter.font.Font(family='helvetica', weight='bold', size=self._size.get()) self._font = tkinter.font.Font(family='helvetica', size=self._size.get()) def _init_grammar(self, parent): # Grammar view. self._prodframe = listframe = Frame(parent) self._prodframe.pack(fill='both', side='left', padx=2) self._prodlist_label = Label(self._prodframe, font=self._boldfont, text='Available Reductions') self._prodlist_label.pack() self._prodlist = Listbox(self._prodframe, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0') self._prodlist.pack(side='right', fill='both', expand=1) self._productions = list(self._parser.grammar().productions()) for production in self._productions: self._prodlist.insert('end', (' %s' % production)) self._prodlist.config(height=min(len(self._productions), 25)) # Add a scrollbar if there are more than 25 productions. if 1: #len(self._productions) > 25: listscroll = Scrollbar(self._prodframe, orient='vertical') self._prodlist.config(yscrollcommand=listscroll.set) listscroll.config(command=self._prodlist.yview) listscroll.pack(side='left', fill='y') # If they select a production, apply it. self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select) # When they hover over a production, highlight it. self._hover = -1 self._prodlist.bind('<Motion>', self._highlight_hover) self._prodlist.bind('<Leave>', self._clear_hover) def _init_bindings(self): # Quit self._top.bind('<Control-q>', self.destroy) self._top.bind('<Control-x>', self.destroy) self._top.bind('<Alt-q>', self.destroy) self._top.bind('<Alt-x>', self.destroy) # Ops (step, shift, reduce, undo) self._top.bind('<space>', self.step) self._top.bind('<s>', self.shift) self._top.bind('<Alt-s>', self.shift) self._top.bind('<Control-s>', self.shift) self._top.bind('<r>', self.reduce) self._top.bind('<Alt-r>', self.reduce) self._top.bind('<Control-r>', self.reduce) self._top.bind('<Delete>', self.reset) self._top.bind('<u>', self.undo) self._top.bind('<Alt-u>', self.undo) self._top.bind('<Control-u>', self.undo) self._top.bind('<Control-z>', self.undo) self._top.bind('<BackSpace>', self.undo) # Misc self._top.bind('<Control-p>', self.postscript) self._top.bind('<Control-h>', self.help) self._top.bind('<F1>', self.help) self._top.bind('<Control-g>', self.edit_grammar) self._top.bind('<Control-t>', self.edit_sentence) # Animation speed control self._top.bind('-', lambda e, a=self._animate: a.set(20)) self._top.bind('=', lambda e, a=self._animate: a.set(10)) self._top.bind('+', lambda e, a=self._animate: a.set(4)) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill='none', side='bottom') Button( buttonframe, text='Step', background='#90c0d0', foreground='black', command=self.step, ).pack(side='left') Button(buttonframe, text='Shift', underline=0, background='#90f090', foreground='black', command=self.shift).pack(side='left') Button(buttonframe, text='Reduce', underline=0, background='#90f090', foreground='black', command=self.reduce).pack(side='left') Button(buttonframe, text='Undo', underline=0, background='#f0a0a0', foreground='black', command=self.undo).pack(side='left') def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Reset Parser', underline=0, command=self.reset, accelerator='Del') filemenu.add_command(label='Print to Postscript', underline=0, command=self.postscript, accelerator='Ctrl-p') filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label='Edit Grammar', underline=5, command=self.edit_grammar, accelerator='Ctrl-g') editmenu.add_command(label='Edit Text', underline=5, command=self.edit_sentence, accelerator='Ctrl-t') menubar.add_cascade(label='Edit', underline=0, menu=editmenu) rulemenu = Menu(menubar, tearoff=0) rulemenu.add_command(label='Step', underline=1, command=self.step, accelerator='Space') rulemenu.add_separator() rulemenu.add_command(label='Shift', underline=0, command=self.shift, accelerator='Ctrl-s') rulemenu.add_command(label='Reduce', underline=0, command=self.reduce, accelerator='Ctrl-r') rulemenu.add_separator() rulemenu.add_command(label='Undo', underline=0, command=self.undo, accelerator='Ctrl-u') menubar.add_cascade(label='Apply', underline=0, menu=rulemenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_checkbutton(label="Show Grammar", underline=0, variable=self._show_grammar, command=self._toggle_grammar) viewmenu.add_separator() viewmenu.add_radiobutton(label='Tiny', variable=self._size, underline=0, value=10, command=self.resize) viewmenu.add_radiobutton(label='Small', variable=self._size, underline=0, value=12, command=self.resize) viewmenu.add_radiobutton(label='Medium', variable=self._size, underline=0, value=14, command=self.resize) viewmenu.add_radiobutton(label='Large', variable=self._size, underline=0, value=18, command=self.resize) viewmenu.add_radiobutton(label='Huge', variable=self._size, underline=0, value=24, command=self.resize) menubar.add_cascade(label='View', underline=0, menu=viewmenu) animatemenu = Menu(menubar, tearoff=0) animatemenu.add_radiobutton(label="No Animation", underline=0, variable=self._animate, value=0) animatemenu.add_radiobutton(label="Slow Animation", underline=0, variable=self._animate, value=20, accelerator='-') animatemenu.add_radiobutton(label="Normal Animation", underline=0, variable=self._animate, value=10, accelerator='=') animatemenu.add_radiobutton(label="Fast Animation", underline=0, variable=self._animate, value=4, accelerator='+') menubar.add_cascade(label="Animate", underline=1, menu=animatemenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label='About', underline=0, command=self.about) helpmenu.add_command(label='Instructions', underline=0, command=self.help, accelerator='F1') menubar.add_cascade(label='Help', underline=0, menu=helpmenu) parent.config(menu=menubar) def _init_feedback(self, parent): self._feedbackframe = feedbackframe = Frame(parent) feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3) self._lastoper_label = Label(feedbackframe, text='Last Operation:', font=self._font) self._lastoper_label.pack(side='left') lastoperframe = Frame(feedbackframe, relief='sunken', border=1) lastoperframe.pack(fill='x', side='right', expand=1, padx=5) self._lastoper1 = Label(lastoperframe, foreground='#007070', background='#f0f0f0', font=self._font) self._lastoper2 = Label(lastoperframe, anchor='w', width=30, foreground='#004040', background='#f0f0f0', font=self._font) self._lastoper1.pack(side='left') self._lastoper2.pack(side='left', fill='x', expand=1) def _init_canvas(self, parent): self._cframe = CanvasFrame(parent, background='white', width=525, closeenough=10, border=2, relief='sunken') self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() self._stackwidgets = [] self._rtextwidgets = [] self._titlebar = canvas.create_rectangle(0, 0, 0, 0, fill='#c0f0f0', outline='black') self._exprline = canvas.create_line(0, 0, 0, 0, dash='.') self._stacktop = canvas.create_line(0, 0, 0, 0, fill='#408080') size = self._size.get() + 4 self._stacklabel = TextWidget(canvas, 'Stack', color='#004040', font=self._boldfont) self._rtextlabel = TextWidget(canvas, 'Remaining Text', color='#004040', font=self._boldfont) self._cframe.add_widget(self._stacklabel) self._cframe.add_widget(self._rtextlabel) ######################################### ## Main draw procedure ######################################### def _redraw(self): scrollregion = self._canvas['scrollregion'].split() (cx1, cy1, cx2, cy2) = [int(c) for c in scrollregion] # Delete the old stack & rtext widgets. for stackwidget in self._stackwidgets: self._cframe.destroy_widget(stackwidget) self._stackwidgets = [] for rtextwidget in self._rtextwidgets: self._cframe.destroy_widget(rtextwidget) self._rtextwidgets = [] # Position the titlebar & exprline (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2 - y1 + 10 self._canvas.coords(self._titlebar, -5000, 0, 5000, y - 4) self._canvas.coords(self._exprline, 0, y * 2 - 10, 5000, y * 2 - 10) # Position the titlebar labels.. (x1, y1, x2, y2) = self._stacklabel.bbox() self._stacklabel.move(5 - x1, 3 - y1) (x1, y1, x2, y2) = self._rtextlabel.bbox() self._rtextlabel.move(cx2 - x2 - 5, 3 - y1) # Draw the stack. stackx = 5 for tok in self._parser.stack(): if isinstance(tok, Tree): attribs = { 'tree_color': '#4080a0', 'tree_width': 2, 'node_font': self._boldfont, 'node_color': '#006060', 'leaf_color': '#006060', 'leaf_font': self._font } widget = tree_to_treesegment(self._canvas, tok, **attribs) widget.label()['color'] = '#000000' else: widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) widget.bind_click(self._popup_reduce) self._stackwidgets.append(widget) self._cframe.add_widget(widget, stackx, y) stackx = widget.bbox()[2] + 10 # Draw the remaining text. rtextwidth = 0 for tok in self._parser.remaining_text(): widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) self._rtextwidgets.append(widget) self._cframe.add_widget(widget, rtextwidth, y) rtextwidth = widget.bbox()[2] + 4 # Allow enough room to shift the next token (for animations) if len(self._rtextwidgets) > 0: stackx += self._rtextwidgets[0].width() # Move the remaining text to the correct location (keep it # right-justified, when possible); and move the remaining text # label, if necessary. stackx = max(stackx, self._stacklabel.width() + 25) rlabelwidth = self._rtextlabel.width() + 10 if stackx >= cx2 - max(rtextwidth, rlabelwidth): cx2 = stackx + max(rtextwidth, rlabelwidth) for rtextwidget in self._rtextwidgets: rtextwidget.move(4 + cx2 - rtextwidth, 0) self._rtextlabel.move(cx2 - self._rtextlabel.bbox()[2] - 5, 0) midx = (stackx + cx2 - max(rtextwidth, rlabelwidth)) / 2 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) (x1, y1, x2, y2) = self._stacklabel.bbox() # Set up binding to allow them to shift a token by dragging it. if len(self._rtextwidgets) > 0: def drag_shift(widget, midx=midx, self=self): if widget.bbox()[0] < midx: self.shift() else: self._redraw() self._rtextwidgets[0].bind_drag(drag_shift) self._rtextwidgets[0].bind_click(self.shift) # Draw the stack top. self._highlight_productions() def _draw_stack_top(self, widget): # hack.. midx = widget.bbox()[2] + 50 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) def _highlight_productions(self): # Highlight the productions that can be reduced. self._prodlist.selection_clear(0, 'end') for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) ######################################### ## Button Callbacks ######################################### def destroy(self, *e): if self._top is None: return self._top.destroy() self._top = None def reset(self, *e): self._parser.initialize(self._sent) self._lastoper1['text'] = 'Reset App' self._lastoper2['text'] = '' self._redraw() def step(self, *e): if self.reduce(): return True elif self.shift(): return True else: if list(self._parser.parses()): self._lastoper1['text'] = 'Finished:' self._lastoper2['text'] = 'Success' else: self._lastoper1['text'] = 'Finished:' self._lastoper2['text'] = 'Failure' def shift(self, *e): if self._animating_lock: return if self._parser.shift(): tok = self._parser.stack()[-1] self._lastoper1['text'] = 'Shift:' self._lastoper2['text'] = '%r' % tok if self._animate.get(): self._animate_shift() else: self._redraw() return True return False def reduce(self, *e): if self._animating_lock: return production = self._parser.reduce() if production: self._lastoper1['text'] = 'Reduce:' self._lastoper2['text'] = '%s' % production if self._animate.get(): self._animate_reduce() else: self._redraw() return production def undo(self, *e): if self._animating_lock: return if self._parser.undo(): self._redraw() def postscript(self, *e): self._cframe.print_to_file() def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs) ######################################### ## Menubar callbacks ######################################### def resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) #self._stacklabel['font'] = ('helvetica', -size-4, 'bold') #self._rtextlabel['font'] = ('helvetica', -size-4, 'bold') #self._lastoper_label['font'] = ('helvetica', -size) #self._lastoper1['font'] = ('helvetica', -size) #self._lastoper2['font'] = ('helvetica', -size) #self._prodlist['font'] = ('helvetica', -size) #self._prodlist_label['font'] = ('helvetica', -size-2, 'bold') self._redraw() def help(self, *e): # The default font's not very legible; try using 'fixed' instead. try: ShowText(self._top, 'Help: Shift-Reduce Parser Application', (__doc__ or '').strip(), width=75, font='fixed') except: ShowText(self._top, 'Help: Shift-Reduce Parser Application', (__doc__ or '').strip(), width=75) def about(self, *e): ABOUT = ("NLTK Shift-Reduce Parser Application\n" + "Written by Edward Loper") TITLE = 'About: Shift-Reduce Parser Application' try: from tkinter.messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def edit_grammar(self, *e): CFGEditor(self._top, self._parser.grammar(), self.set_grammar) def set_grammar(self, grammar): self._parser.set_grammar(grammar) self._productions = list(grammar.productions()) self._prodlist.delete(0, 'end') for production in self._productions: self._prodlist.insert('end', (' %s' % production)) def edit_sentence(self, *e): sentence = " ".join(self._sent) title = 'Edit Text' instr = 'Enter a new sentence to parse.' EntryDialog(self._top, sentence, instr, self.set_sentence, title) def set_sentence(self, sent): self._sent = sent.split() #[XX] use tagged? self.reset() ######################################### ## Reduce Production Selection ######################################### def _toggle_grammar(self, *e): if self._show_grammar.get(): self._prodframe.pack(fill='both', side='left', padx=2, after=self._feedbackframe) self._lastoper1['text'] = 'Show Grammar' else: self._prodframe.pack_forget() self._lastoper1['text'] = 'Hide Grammar' self._lastoper2['text'] = '' def _prodlist_select(self, event): selection = self._prodlist.curselection() if len(selection) != 1: return index = int(selection[0]) production = self._parser.reduce(self._productions[index]) if production: self._lastoper1['text'] = 'Reduce:' self._lastoper2['text'] = '%s' % production if self._animate.get(): self._animate_reduce() else: self._redraw() else: # Reset the production selections. self._prodlist.selection_clear(0, 'end') for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) def _popup_reduce(self, widget): # Remove old commands. productions = self._parser.reducible_productions() if len(productions) == 0: return self._reduce_menu.delete(0, 'end') for production in productions: self._reduce_menu.add_command(label=str(production), command=self.reduce) self._reduce_menu.post(self._canvas.winfo_pointerx(), self._canvas.winfo_pointery()) ######################################### ## Animations ######################################### def _animate_shift(self): # What widget are we shifting? widget = self._rtextwidgets[0] # Where are we shifting from & to? right = widget.bbox()[0] if len(self._stackwidgets) == 0: left = 5 else: left = self._stackwidgets[-1].bbox()[2] + 10 # Start animating. dt = self._animate.get() dx = (left - right) * 1.0 / dt self._animate_shift_frame(dt, widget, dx) def _animate_shift_frame(self, frame, widget, dx): if frame > 0: self._animating_lock = 1 widget.move(dx, 0) self._top.after(10, self._animate_shift_frame, frame - 1, widget, dx) else: # but: stacktop?? # Shift the widget to the stack. del self._rtextwidgets[0] self._stackwidgets.append(widget) self._animating_lock = 0 # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() def _animate_reduce(self): # What widgets are we shifting? numwidgets = len(self._parser.stack()[-1]) # number of children widgets = self._stackwidgets[-numwidgets:] # How far are we moving? if isinstance(widgets[0], TreeSegmentWidget): ydist = 15 + widgets[0].label().height() else: ydist = 15 + widgets[0].height() # Start animating. dt = self._animate.get() dy = ydist * 2.0 / dt self._animate_reduce_frame(dt / 2, widgets, dy) def _animate_reduce_frame(self, frame, widgets, dy): if frame > 0: self._animating_lock = 1 for widget in widgets: widget.move(0, dy) self._top.after(10, self._animate_reduce_frame, frame - 1, widgets, dy) else: del self._stackwidgets[-len(widgets):] for widget in widgets: self._cframe.remove_widget(widget) tok = self._parser.stack()[-1] if not isinstance(tok, Tree): raise ValueError() label = TextWidget(self._canvas, str(tok.label()), color='#006060', font=self._boldfont) widget = TreeSegmentWidget(self._canvas, label, widgets, width=2) (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2 - y1 + 10 if not self._stackwidgets: x = 5 else: x = self._stackwidgets[-1].bbox()[2] + 10 self._cframe.add_widget(widget, x, y) self._stackwidgets.append(widget) # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() # # Delete the old widgets.. # del self._stackwidgets[-len(widgets):] # for widget in widgets: # self._cframe.destroy_widget(widget) # # # Make a new one. # tok = self._parser.stack()[-1] # if isinstance(tok, Tree): # attribs = {'tree_color': '#4080a0', 'tree_width': 2, # 'node_font': bold, 'node_color': '#006060', # 'leaf_color': '#006060', 'leaf_font':self._font} # widget = tree_to_treesegment(self._canvas, tok.type(), # **attribs) # widget.node()['color'] = '#000000' # else: # widget = TextWidget(self._canvas, tok.type(), # color='#000000', font=self._font) # widget.bind_click(self._popup_reduce) # (x1, y1, x2, y2) = self._stacklabel.bbox() # y = y2-y1+10 # if not self._stackwidgets: x = 5 # else: x = self._stackwidgets[-1].bbox()[2] + 10 # self._cframe.add_widget(widget, x, y) # self._stackwidgets.append(widget) #self._redraw() self._animating_lock = 0 ######################################### ## Hovering. ######################################### def _highlight_hover(self, event): # What production are we hovering over? index = self._prodlist.nearest(event.y) if self._hover == index: return # Clear any previous hover highlighting. self._clear_hover() # If the production corresponds to an available reduction, # highlight the stack. selection = [int(s) for s in self._prodlist.curselection()] if index in selection: rhslen = len(self._productions[index].rhs()) for stackwidget in self._stackwidgets[-rhslen:]: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()['color'] = '#00a000' else: stackwidget['color'] = '#00a000' # Remember what production we're hovering over. self._hover = index def _clear_hover(self, *event): # Clear any previous hover highlighting. if self._hover == -1: return self._hover = -1 for stackwidget in self._stackwidgets: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()['color'] = 'black' else: stackwidget['color'] = 'black'
class RecursiveDescentApp(object): """ A graphical tool for exploring the recursive descent parser. The tool displays the parser's tree and the remaining text, and allows the user to control the parser's operation. In particular, the user can expand subtrees on the frontier, match tokens on the frontier against the text, and backtrack. A "step" button simply steps through the parsing process, performing the operations that ``RecursiveDescentParser`` would use. """ def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingRecursiveDescentParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Recursive Descent Parser Application') # Set up key bindings. self._init_bindings() # Initialize the fonts. self._init_fonts(self._top) # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animation_frames = IntVar(self._top) self._animation_frames.set(5) self._animating_lock = 0 self._autostep = 0 # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # Initialize the parser. self._parser.initialize(self._sent) # Resize callback self._canvas.bind('<Configure>', self._configure) ######################################### ## Initialization Helpers ######################################### def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = tkinter.font.Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = tkinter.font.Font(family='helvetica', weight='bold', size=self._size.get()) self._font = tkinter.font.Font(family='helvetica', size=self._size.get()) if self._size.get() < 0: big = self._size.get() - 2 else: big = self._size.get() + 2 self._bigfont = tkinter.font.Font(family='helvetica', weight='bold', size=big) def _init_grammar(self, parent): # Grammar view. self._prodframe = listframe = Frame(parent) self._prodframe.pack(fill='both', side='left', padx=2) self._prodlist_label = Label(self._prodframe, font=self._boldfont, text='Available Expansions') self._prodlist_label.pack() self._prodlist = Listbox(self._prodframe, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0') self._prodlist.pack(side='right', fill='both', expand=1) self._productions = list(self._parser.grammar().productions()) for production in self._productions: self._prodlist.insert('end', (' %s' % production)) self._prodlist.config(height=min(len(self._productions), 25)) # Add a scrollbar if there are more than 25 productions. if len(self._productions) > 25: listscroll = Scrollbar(self._prodframe, orient='vertical') self._prodlist.config(yscrollcommand=listscroll.set) listscroll.config(command=self._prodlist.yview) listscroll.pack(side='left', fill='y') # If they select a production, apply it. self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select) def _init_bindings(self): # Key bindings are a good thing. self._top.bind('<Control-q>', self.destroy) self._top.bind('<Control-x>', self.destroy) self._top.bind('<Escape>', self.destroy) self._top.bind('e', self.expand) #self._top.bind('<Alt-e>', self.expand) #self._top.bind('<Control-e>', self.expand) self._top.bind('m', self.match) self._top.bind('<Alt-m>', self.match) self._top.bind('<Control-m>', self.match) self._top.bind('b', self.backtrack) self._top.bind('<Alt-b>', self.backtrack) self._top.bind('<Control-b>', self.backtrack) self._top.bind('<Control-z>', self.backtrack) self._top.bind('<BackSpace>', self.backtrack) self._top.bind('a', self.autostep) #self._top.bind('<Control-a>', self.autostep) self._top.bind('<Control-space>', self.autostep) self._top.bind('<Control-c>', self.cancel_autostep) self._top.bind('<space>', self.step) self._top.bind('<Delete>', self.reset) self._top.bind('<Control-p>', self.postscript) #self._top.bind('<h>', self.help) #self._top.bind('<Alt-h>', self.help) self._top.bind('<Control-h>', self.help) self._top.bind('<F1>', self.help) #self._top.bind('<g>', self.toggle_grammar) #self._top.bind('<Alt-g>', self.toggle_grammar) #self._top.bind('<Control-g>', self.toggle_grammar) self._top.bind('<Control-g>', self.edit_grammar) self._top.bind('<Control-t>', self.edit_sentence) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill='none', side='bottom', padx=3, pady=2) Button( buttonframe, text='Step', background='#90c0d0', foreground='black', command=self.step, ).pack(side='left') Button( buttonframe, text='Autostep', background='#90c0d0', foreground='black', command=self.autostep, ).pack(side='left') Button(buttonframe, text='Expand', underline=0, background='#90f090', foreground='black', command=self.expand).pack(side='left') Button(buttonframe, text='Match', underline=0, background='#90f090', foreground='black', command=self.match).pack(side='left') Button(buttonframe, text='Backtrack', underline=0, background='#f0a0a0', foreground='black', command=self.backtrack).pack(side='left') # Replace autostep... # self._autostep_button = Button(buttonframe, text='Autostep', # underline=0, command=self.autostep) # self._autostep_button.pack(side='left') def _configure(self, event): self._autostep = 0 (x1, y1, x2, y2) = self._cframe.scrollregion() y2 = event.height - 6 self._canvas['scrollregion'] = '%d %d %d %d' % (x1, y1, x2, y2) self._redraw() def _init_feedback(self, parent): self._feedbackframe = feedbackframe = Frame(parent) feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3) self._lastoper_label = Label(feedbackframe, text='Last Operation:', font=self._font) self._lastoper_label.pack(side='left') lastoperframe = Frame(feedbackframe, relief='sunken', border=1) lastoperframe.pack(fill='x', side='right', expand=1, padx=5) self._lastoper1 = Label(lastoperframe, foreground='#007070', background='#f0f0f0', font=self._font) self._lastoper2 = Label(lastoperframe, anchor='w', width=30, foreground='#004040', background='#f0f0f0', font=self._font) self._lastoper1.pack(side='left') self._lastoper2.pack(side='left', fill='x', expand=1) def _init_canvas(self, parent): self._cframe = CanvasFrame( parent, background='white', #width=525, height=250, closeenough=10, border=2, relief='sunken') self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() # Initially, there's no tree or text self._tree = None self._textwidgets = [] self._textline = None def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Reset Parser', underline=0, command=self.reset, accelerator='Del') filemenu.add_command(label='Print to Postscript', underline=0, command=self.postscript, accelerator='Ctrl-p') filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label='Edit Grammar', underline=5, command=self.edit_grammar, accelerator='Ctrl-g') editmenu.add_command(label='Edit Text', underline=5, command=self.edit_sentence, accelerator='Ctrl-t') menubar.add_cascade(label='Edit', underline=0, menu=editmenu) rulemenu = Menu(menubar, tearoff=0) rulemenu.add_command(label='Step', underline=1, command=self.step, accelerator='Space') rulemenu.add_separator() rulemenu.add_command(label='Match', underline=0, command=self.match, accelerator='Ctrl-m') rulemenu.add_command(label='Expand', underline=0, command=self.expand, accelerator='Ctrl-e') rulemenu.add_separator() rulemenu.add_command(label='Backtrack', underline=0, command=self.backtrack, accelerator='Ctrl-b') menubar.add_cascade(label='Apply', underline=0, menu=rulemenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_checkbutton(label="Show Grammar", underline=0, variable=self._show_grammar, command=self._toggle_grammar) viewmenu.add_separator() viewmenu.add_radiobutton(label='Tiny', variable=self._size, underline=0, value=10, command=self.resize) viewmenu.add_radiobutton(label='Small', variable=self._size, underline=0, value=12, command=self.resize) viewmenu.add_radiobutton(label='Medium', variable=self._size, underline=0, value=14, command=self.resize) viewmenu.add_radiobutton(label='Large', variable=self._size, underline=0, value=18, command=self.resize) viewmenu.add_radiobutton(label='Huge', variable=self._size, underline=0, value=24, command=self.resize) menubar.add_cascade(label='View', underline=0, menu=viewmenu) animatemenu = Menu(menubar, tearoff=0) animatemenu.add_radiobutton(label="No Animation", underline=0, variable=self._animation_frames, value=0) animatemenu.add_radiobutton(label="Slow Animation", underline=0, variable=self._animation_frames, value=10, accelerator='-') animatemenu.add_radiobutton(label="Normal Animation", underline=0, variable=self._animation_frames, value=5, accelerator='=') animatemenu.add_radiobutton(label="Fast Animation", underline=0, variable=self._animation_frames, value=2, accelerator='+') menubar.add_cascade(label="Animate", underline=1, menu=animatemenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label='About', underline=0, command=self.about) helpmenu.add_command(label='Instructions', underline=0, command=self.help, accelerator='F1') menubar.add_cascade(label='Help', underline=0, menu=helpmenu) parent.config(menu=menubar) ######################################### ## Helper ######################################### def _get(self, widget, treeloc): for i in treeloc: widget = widget.subtrees()[i] if isinstance(widget, TreeSegmentWidget): widget = widget.label() return widget ######################################### ## Main draw procedure ######################################### def _redraw(self): canvas = self._canvas # Delete the old tree, widgets, etc. if self._tree is not None: self._cframe.destroy_widget(self._tree) for twidget in self._textwidgets: self._cframe.destroy_widget(twidget) if self._textline is not None: self._canvas.delete(self._textline) # Draw the tree. helv = ('helvetica', -self._size.get()) bold = ('helvetica', -self._size.get(), 'bold') attribs = { 'tree_color': '#000000', 'tree_width': 2, 'node_font': bold, 'leaf_font': helv, } tree = self._parser.tree() self._tree = tree_to_treesegment(canvas, tree, **attribs) self._cframe.add_widget(self._tree, 30, 5) # Draw the text. helv = ('helvetica', -self._size.get()) bottom = y = self._cframe.scrollregion()[3] self._textwidgets = [ TextWidget(canvas, word, font=self._font) for word in self._sent ] for twidget in self._textwidgets: self._cframe.add_widget(twidget, 0, 0) twidget.move(0, bottom - twidget.bbox()[3] - 5) y = min(y, twidget.bbox()[1]) # Draw a line over the text, to separate it from the tree. self._textline = canvas.create_line(-5000, y - 5, 5000, y - 5, dash='.') # Highlight appropriate nodes. self._highlight_nodes() self._highlight_prodlist() # Make sure the text lines up. self._position_text() def _redraw_quick(self): # This should be more-or-less sufficient after an animation. self._highlight_nodes() self._highlight_prodlist() self._position_text() def _highlight_nodes(self): # Highlight the list of nodes to be checked. bold = ('helvetica', -self._size.get(), 'bold') for treeloc in self._parser.frontier()[:1]: self._get(self._tree, treeloc)['color'] = '#20a050' self._get(self._tree, treeloc)['font'] = bold for treeloc in self._parser.frontier()[1:]: self._get(self._tree, treeloc)['color'] = '#008080' def _highlight_prodlist(self): # Highlight the productions that can be expanded. # Boy, too bad tkinter doesn't implement Listbox.itemconfig; # that would be pretty useful here. self._prodlist.delete(0, 'end') expandable = self._parser.expandable_productions() untried = self._parser.untried_expandable_productions() productions = self._productions for index in range(len(productions)): if productions[index] in expandable: if productions[index] in untried: self._prodlist.insert(index, ' %s' % productions[index]) else: self._prodlist.insert(index, ' %s (TRIED)' % productions[index]) self._prodlist.selection_set(index) else: self._prodlist.insert(index, ' %s' % productions[index]) def _position_text(self): # Line up the text widgets that are matched against the tree numwords = len(self._sent) num_matched = numwords - len(self._parser.remaining_text()) leaves = self._tree_leaves()[:num_matched] xmax = self._tree.bbox()[0] for i in range(0, len(leaves)): widget = self._textwidgets[i] leaf = leaves[i] widget['color'] = '#006040' leaf['color'] = '#006040' widget.move(leaf.bbox()[0] - widget.bbox()[0], 0) xmax = widget.bbox()[2] + 10 # Line up the text widgets that are not matched against the tree. for i in range(len(leaves), numwords): widget = self._textwidgets[i] widget['color'] = '#a0a0a0' widget.move(xmax - widget.bbox()[0], 0) xmax = widget.bbox()[2] + 10 # If we have a complete parse, make everything green :) if self._parser.currently_complete(): for twidget in self._textwidgets: twidget['color'] = '#00a000' # Move the matched leaves down to the text. for i in range(0, len(leaves)): widget = self._textwidgets[i] leaf = leaves[i] dy = widget.bbox()[1] - leaf.bbox()[3] - 10.0 dy = max(dy, leaf.parent().label().bbox()[3] - leaf.bbox()[3] + 10) leaf.move(0, dy) def _tree_leaves(self, tree=None): if tree is None: tree = self._tree if isinstance(tree, TreeSegmentWidget): leaves = [] for child in tree.subtrees(): leaves += self._tree_leaves(child) return leaves else: return [tree] ######################################### ## Button Callbacks ######################################### def destroy(self, *e): self._autostep = 0 if self._top is None: return self._top.destroy() self._top = None def reset(self, *e): self._autostep = 0 self._parser.initialize(self._sent) self._lastoper1['text'] = 'Reset Application' self._lastoper2['text'] = '' self._redraw() def autostep(self, *e): if self._animation_frames.get() == 0: self._animation_frames.set(2) if self._autostep: self._autostep = 0 else: self._autostep = 1 self._step() def cancel_autostep(self, *e): #self._autostep_button['text'] = 'Autostep' self._autostep = 0 # Make sure to stop auto-stepping if we get any user input. def step(self, *e): self._autostep = 0 self._step() def match(self, *e): self._autostep = 0 self._match() def expand(self, *e): self._autostep = 0 self._expand() def backtrack(self, *e): self._autostep = 0 self._backtrack() def _step(self): if self._animating_lock: return # Try expanding, matching, and backtracking (in that order) if self._expand(): pass elif self._parser.untried_match() and self._match(): pass elif self._backtrack(): pass else: self._lastoper1['text'] = 'Finished' self._lastoper2['text'] = '' self._autostep = 0 # Check if we just completed a parse. if self._parser.currently_complete(): self._autostep = 0 self._lastoper2['text'] += ' [COMPLETE PARSE]' def _expand(self, *e): if self._animating_lock: return old_frontier = self._parser.frontier() rv = self._parser.expand() if rv is not None: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = rv self._prodlist.selection_clear(0, 'end') index = self._productions.index(rv) self._prodlist.selection_set(index) self._animate_expand(old_frontier[0]) return True else: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = '(all expansions tried)' return False def _match(self, *e): if self._animating_lock: return old_frontier = self._parser.frontier() rv = self._parser.match() if rv is not None: self._lastoper1['text'] = 'Match:' self._lastoper2['text'] = rv self._animate_match(old_frontier[0]) return True else: self._lastoper1['text'] = 'Match:' self._lastoper2['text'] = '(failed)' return False def _backtrack(self, *e): if self._animating_lock: return if self._parser.backtrack(): elt = self._parser.tree() for i in self._parser.frontier()[0]: elt = elt[i] self._lastoper1['text'] = 'Backtrack' self._lastoper2['text'] = '' if isinstance(elt, Tree): self._animate_backtrack(self._parser.frontier()[0]) else: self._animate_match_backtrack(self._parser.frontier()[0]) return True else: self._autostep = 0 self._lastoper1['text'] = 'Finished' self._lastoper2['text'] = '' return False def about(self, *e): ABOUT = ("NLTK Recursive Descent Parser Application\n" + "Written by Edward Loper") TITLE = 'About: Recursive Descent Parser Application' try: from tkinter.messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def help(self, *e): self._autostep = 0 # The default font's not very legible; try using 'fixed' instead. try: ShowText(self._top, 'Help: Recursive Descent Parser Application', (__doc__ or '').strip(), width=75, font='fixed') except: ShowText(self._top, 'Help: Recursive Descent Parser Application', (__doc__ or '').strip(), width=75) def postscript(self, *e): self._autostep = 0 self._cframe.print_to_file() def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs) def resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) self._bigfont.configure(size=-(abs(size + 2))) self._redraw() ######################################### ## Expand Production Selection ######################################### def _toggle_grammar(self, *e): if self._show_grammar.get(): self._prodframe.pack(fill='both', side='left', padx=2, after=self._feedbackframe) self._lastoper1['text'] = 'Show Grammar' else: self._prodframe.pack_forget() self._lastoper1['text'] = 'Hide Grammar' self._lastoper2['text'] = '' # def toggle_grammar(self, *e): # self._show_grammar = not self._show_grammar # if self._show_grammar: # self._prodframe.pack(fill='both', expand='y', side='left', # after=self._feedbackframe) # self._lastoper1['text'] = 'Show Grammar' # else: # self._prodframe.pack_forget() # self._lastoper1['text'] = 'Hide Grammar' # self._lastoper2['text'] = '' def _prodlist_select(self, event): selection = self._prodlist.curselection() if len(selection) != 1: return index = int(selection[0]) old_frontier = self._parser.frontier() production = self._parser.expand(self._productions[index]) if production: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = production self._prodlist.selection_clear(0, 'end') self._prodlist.selection_set(index) self._animate_expand(old_frontier[0]) else: # Reset the production selections. self._prodlist.selection_clear(0, 'end') for prod in self._parser.expandable_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) ######################################### ## Animation ######################################### def _animate_expand(self, treeloc): oldwidget = self._get(self._tree, treeloc) oldtree = oldwidget.parent() top = not isinstance(oldtree.parent(), TreeSegmentWidget) tree = self._parser.tree() for i in treeloc: tree = tree[i] widget = tree_to_treesegment(self._canvas, tree, node_font=self._boldfont, leaf_color='white', tree_width=2, tree_color='white', node_color='white', leaf_font=self._font) widget.label()['color'] = '#20a050' (oldx, oldy) = oldtree.label().bbox()[:2] (newx, newy) = widget.label().bbox()[:2] widget.move(oldx - newx, oldy - newy) if top: self._cframe.add_widget(widget, 0, 5) widget.move(30 - widget.label().bbox()[0], 0) self._tree = widget else: oldtree.parent().replace_child(oldtree, widget) # Move the children over so they don't overlap. # Line the children up in a strange way. if widget.subtrees(): dx = (oldx + widget.label().width() / 2 - widget.subtrees()[0].bbox()[0] / 2 - widget.subtrees()[0].bbox()[2] / 2) for subtree in widget.subtrees(): subtree.move(dx, 0) self._makeroom(widget) if top: self._cframe.destroy_widget(oldtree) else: oldtree.destroy() colors = [ 'gray%d' % (10 * int(10 * x / self._animation_frames.get())) for x in range(self._animation_frames.get(), 0, -1) ] # Move the text string down, if necessary. dy = widget.bbox()[3] + 30 - self._canvas.coords(self._textline)[1] if dy > 0: for twidget in self._textwidgets: twidget.move(0, dy) self._canvas.move(self._textline, 0, dy) self._animate_expand_frame(widget, colors) def _makeroom(self, treeseg): """ Make sure that no sibling tree bbox's overlap. """ parent = treeseg.parent() if not isinstance(parent, TreeSegmentWidget): return index = parent.subtrees().index(treeseg) # Handle siblings to the right rsiblings = parent.subtrees()[index + 1:] if rsiblings: dx = treeseg.bbox()[2] - rsiblings[0].bbox()[0] + 10 for sibling in rsiblings: sibling.move(dx, 0) # Handle siblings to the left if index > 0: lsibling = parent.subtrees()[index - 1] dx = max(0, lsibling.bbox()[2] - treeseg.bbox()[0] + 10) treeseg.move(dx, 0) # Keep working up the tree. self._makeroom(parent) def _animate_expand_frame(self, widget, colors): if len(colors) > 0: self._animating_lock = 1 widget['color'] = colors[0] for subtree in widget.subtrees(): if isinstance(subtree, TreeSegmentWidget): subtree.label()['color'] = colors[0] else: subtree['color'] = colors[0] self._top.after(50, self._animate_expand_frame, widget, colors[1:]) else: widget['color'] = 'black' for subtree in widget.subtrees(): if isinstance(subtree, TreeSegmentWidget): subtree.label()['color'] = 'black' else: subtree['color'] = 'black' self._redraw_quick() widget.label()['color'] = 'black' self._animating_lock = 0 if self._autostep: self._step() def _animate_backtrack(self, treeloc): # Flash red first, if we're animating. if self._animation_frames.get() == 0: colors = [] else: colors = ['#a00000', '#000000', '#a00000'] colors += [ 'gray%d' % (10 * int(10 * x / (self._animation_frames.get()))) for x in range(1, self._animation_frames.get() + 1) ] widgets = [self._get(self._tree, treeloc).parent()] for subtree in widgets[0].subtrees(): if isinstance(subtree, TreeSegmentWidget): widgets.append(subtree.label()) else: widgets.append(subtree) self._animate_backtrack_frame(widgets, colors) def _animate_backtrack_frame(self, widgets, colors): if len(colors) > 0: self._animating_lock = 1 for widget in widgets: widget['color'] = colors[0] self._top.after(50, self._animate_backtrack_frame, widgets, colors[1:]) else: for widget in widgets[0].subtrees(): widgets[0].remove_child(widget) widget.destroy() self._redraw_quick() self._animating_lock = 0 if self._autostep: self._step() def _animate_match_backtrack(self, treeloc): widget = self._get(self._tree, treeloc) node = widget.parent().label() dy = (1.0 * (node.bbox()[3] - widget.bbox()[1] + 14) / max(1, self._animation_frames.get())) self._animate_match_backtrack_frame(self._animation_frames.get(), widget, dy) def _animate_match(self, treeloc): widget = self._get(self._tree, treeloc) dy = ((self._textwidgets[0].bbox()[1] - widget.bbox()[3] - 10.0) / max(1, self._animation_frames.get())) self._animate_match_frame(self._animation_frames.get(), widget, dy) def _animate_match_frame(self, frame, widget, dy): if frame > 0: self._animating_lock = 1 widget.move(0, dy) self._top.after(10, self._animate_match_frame, frame - 1, widget, dy) else: widget['color'] = '#006040' self._redraw_quick() self._animating_lock = 0 if self._autostep: self._step() def _animate_match_backtrack_frame(self, frame, widget, dy): if frame > 0: self._animating_lock = 1 widget.move(0, dy) self._top.after(10, self._animate_match_backtrack_frame, frame - 1, widget, dy) else: widget.parent().remove_child(widget) widget.destroy() self._animating_lock = 0 if self._autostep: self._step() def edit_grammar(self, *e): CFGEditor(self._top, self._parser.grammar(), self.set_grammar) def set_grammar(self, grammar): self._parser.set_grammar(grammar) self._productions = list(grammar.productions()) self._prodlist.delete(0, 'end') for production in self._productions: self._prodlist.insert('end', (' %s' % production)) def edit_sentence(self, *e): sentence = " ".join(self._sent) title = 'Edit Text' instr = 'Enter a new sentence to parse.' EntryDialog(self._top, sentence, instr, self.set_sentence, title) def set_sentence(self, sentence): self._sent = sentence.split() #[XX] use tagged? self.reset()
class PredictionInputPanel(LabelFrame): def __init__(self, parent, img_inputs, classifier, root, app): self.img_inputs = img_inputs self.classifier = classifier LabelFrame.__init__(self, parent, text='Image Input/s', padx=10, pady=10, labelanchor='nw') self.pack(side=tk.LEFT, expand=False, fill=tk.BOTH) self.btn_select_images = Button(self, width=12, text='Select Images', command=self.select_images) self.btn_select_images.grid(row=2, column=1, pady=5, sticky='e') # Create scrollbars for image listbox (lb) self.scrollbar_v_lb = Scrollbar(self, orient=tk.VERTICAL) self.scrollbar_h_lb = Scrollbar(self, orient=tk.HORIZONTAL) self.scrollbar_v_lb.grid(row=0, column=2, sticky='nws') self.scrollbar_h_lb.grid(row=1, column=0, columnspan=2, sticky='wse') # Display all images selected by user in a listbox self.listbox = Listbox(self, width=40, height=15, yscrollcommand=self.scrollbar_v_lb.set, xscrollcommand=self.scrollbar_h_lb.set) self.listbox.grid(row=0, column=0, columnspan=2) # Create a label that displays '[count] image/s selected' self.label_image_count = Label(self, width=20, padx=5, pady=3, text='No image selected.', anchor='w', borderwidth=2, relief='ridge') self.label_image_count.grid(row=2, column=0, sticky='w') self.classifier.model_name.set(' No model selected.') self.model_name_display = Entry( self, textvariable=self.classifier.model_name, width=25) self.btn_select_model = Button( self, text='Select Model', width=12, command=lambda: self.classifier.select_model(self)) self.btn_classify = Button( self, text='CLASSIFY', width=35, command=lambda: self.classifier.classify(root, app)) # Might transfer the first half of this method (actual image selection part) to a separate method inside ImageData Class # ... and leave the 2nd half (display / view part) here def select_images(self): # Clear listbox and other lists everytime the user clicks the button and selects a new set of files # ...to prevent duplicate images from being appended in the listbox self.listbox.delete(0, tk.END) self.img_inputs.selected_images.clear() self.img_inputs.selected_images_paths.clear() # fd.askopenfilenames() returns 'absolute' paths of the selected images. Save the paths in a list. self.img_inputs.selected_images_paths = list( fd.askopenfilenames(filetypes=(('jpeg files', '*.jpg'), ('png files', '*.png')))) # Get directory of selected images if len(self.img_inputs.selected_images_paths) > 0: self.img_inputs.selected_images_dir = os.path.dirname( self.img_inputs.selected_images_paths[0]) # Display filenames/paths of selected images in listbox for image_path in self.img_inputs.selected_images_paths: self.listbox.insert(tk.END, image_path) # Extract just the file names from the absolue paths for image_path in self.img_inputs.selected_images_paths: filename = image_path[(len(self.img_inputs.selected_images_dir) + 1):] self.img_inputs.selected_images.append(filename) input_count = len(self.img_inputs.selected_images) self.label_image_count.configure(text=str(input_count) + ' image/s selected.') self.show_classification_widgets() def show_classification_widgets(self): self.model_name_display.grid(row=4, column=0, sticky='w') self.btn_select_model.grid(row=4, column=1, sticky='e')
class MainAppController(Frame): """ Main Application for GUI """ def __init__(self, parent): """ Initialize Main Application """ Frame.__init__(self, parent) # create a style object style = Style() style.configure('D.TButton', foreground='red3') style.configure('R.TButton', foreground='DodgerBlue4', font=("TkTextFont", 9, 'bold')) style.configure('B.TButton', foreground='FireBrick4', font=("TkTextFont", 9, 'bold')) # Left frame, column 1 left_frame = Frame(master=self) left_frame.grid(row=1, column=1, padx=30, pady=35, rowspan=3) # Middle frame (info text, column 2) middle_frame = Frame(master=self) middle_frame.grid(row=1, column=2, padx=30, pady=35, rowspan=3) # Right frame (statistics, column 3) right_frame = Frame(master=self) right_frame.grid(row=1, column=3, padx=30, pady=35, rowspan=2) # LEFT FRAME WIDGET Label(left_frame, text="Book ID", font=("TkTextFont", 11)).grid(row=1, column=1, columnspan=3) self._book_list = Listbox(left_frame, height=10, width=10, font=("TkTextFont", 11), bg='LightSalmon2') self._book_list.grid(row=2, column=1) self._book_list.configure(justify="center") # Call this on select self._book_list.bind("<<ListboxSelect>>", self._update_textbox) # MIDDLE FRAME WIDGET Label(middle_frame, text="Book Summary", font=("TkTextFont", 11)).grid(row=1, column=2, columnspan=7) self._info_text = Text(master=middle_frame, height=10, width=45, font=("TkTextFont", 11), bg='plum2') self._info_text.grid(row=2, column=2, columnspan=7) self._info_text.tag_configure("bold", font=("TkTextFont", 10, "bold")) # RIGHT FRAME WIDGET Label(right_frame, text="Book Statistics", font=("TkTextFont", 11)).grid(row=1, column=1, columnspan=3) self._book_stat = Text(master=right_frame, height=10.5, width=30, font=("TkTextFont", 10), bg='LightSalmon2') self._book_stat.grid(row=2, column=1, rowspan=3) self._book_stat.tag_configure("bold", font=("TkTextFont", 10, "bold")) # Drop Down menu to add a book self._add_var = StringVar(left_frame) choices = ['eBook', 'Textbook'] OptionMenu(middle_frame, self._add_var, 'Select Type', *choices).grid(row=3, column=2, pady=5, columnspan=4) # Drop Down menu to update a book self._update_var = StringVar(left_frame) choices = ['eBook', 'Textbook'] OptionMenu(middle_frame, self._update_var, 'Select Type', *choices).grid(row=3, column=3, pady=5, columnspan=7) # A couple buttons - using TTK Button(left_frame, text="Delete Book", width=13, command=self._delete_book, style='D.TButton').grid(row=3, column=1, pady=5) Button(left_frame, text="Quit", width=13, command=self._quit_callback).grid(row=4, column=1) Button(middle_frame, text="Add Book", width=13, command=self._add_book).grid(row=4, column=2, columnspan=4) Button(middle_frame, text="Update Book", width=13, command=self._update_book).grid(row=4, column=3, columnspan=7) Button(right_frame, text="Borrow Book", width=13, command=self._borrow_cb, style='B.TButton').grid(row=5, column=1, pady=5) Button(right_frame, text="Return Book", width=13, command=self._return_cb, style='R.TButton').grid(row=6, column=1) # Now update the list and Statistics self._update_book_list() def _update_textbox(self, *args): """ Updates the info text box on the right, based on the current ID selected """ # This is a list, so we take just the first item (could be multi select...) try: selected_index = self._book_list.curselection()[0] except IndexError: return None book_id = self._book_list.get(selected_index) # Make a GET request r = requests.get( f"http://localhost:5000/library_manager/book/{book_id}") # Clear the text box self._info_text.delete(1.0, tk.END) # Check the request status code if r.status_code != 200: self._info_text.insert(tk.END, "Error running the request!") # For every item (key, value) in the JSON response, display them: for k, v in r.json().items(): self._info_text.insert(tk.END, f"{k.capitalize()}\t\t", "bold") self._info_text.insert(tk.END, f"{v}\n") self._update_book_stat() def _update_book_list(self): """ Update the List of Books """ r = requests.get("http://localhost:5000/library_manager/all") self._book_list.delete(0, tk.END) for s in r.json()["ebook"]: self._book_list.insert(tk.END, '{:^}'.format(s['book_id'])) self._book_list.itemconfig(tk.END, {'fg': 'Blue4'}) if s['is_borrowed']: self._book_list.itemconfig(tk.END, {'bg': 'khaki1'}) for s in r.json()["textbook"]: self._book_list.insert(tk.END, '{:^}'.format(s['book_id'])) self._book_list.itemconfig(tk.END, {'fg': 'Brown4'}) if s['is_borrowed']: self._book_list.itemconfig(tk.END, {'bg': 'khaki1'}) self._update_book_stat() def _update_book_stat(self): """ Update the List of Books """ r = requests.get("http://localhost:5000/library_manager/all/stats") self._book_stat.delete(1.0, tk.END) for k, v in r.json().items(): self._book_stat.insert(tk.END, f"{k}\t\t\t", "bold") self._book_stat.insert(tk.END, f"{v}\n") def _borrow_cb(self): """Borrow any book with the selected ID""" if not self._book_list.curselection(): mb.showerror('Error : Item not selected', 'Please select a book.') else: selected_index = self._book_list.curselection()[0] book_id = self._book_list.get(selected_index) r = requests.get( f"http://127.0.0.1:5000/library_manager/book/{book_id}") if r.json()['is_borrowed']: mb.showerror('Error : Bad selection', 'Book is already borrowed.') else: response = requests.put( f"http://127.0.0.1:5000/library_manager/{book_id}/borrow") if response.status_code == 200: self._update_book_list() def _return_cb(self): """Return any book with the selected ID to library""" if not self._book_list.curselection(): mb.showerror('Error : Item not selected', 'Please select a book.') else: selected_index = self._book_list.curselection()[0] book_id = self._book_list.get(selected_index) r = requests.get( f"http://127.0.0.1:5000/library_manager/book/{book_id}") if not r.json()['is_borrowed']: mb.showerror('Error : Bad selection', 'Book is already returned.') else: response = requests.put( f"http://127.0.0.1:5000/library_manager/{book_id}/return_book" ) if response.status_code == 200: self._update_book_list() def _add_ebook(self): """ Add eBook Popup """ self._popup_win = tk.Toplevel() self._popup = AddeBookPopup(self._popup_win, self._close_book_cb) def _add_textbook(self): """ Add Textbook Popup """ self._popup_win = tk.Toplevel() self._popup = AddTextbookPopup(self._popup_win, self._close_book_cb) def _add_book(self): """Redirect add book based on the type""" if self._add_var.get() == 'eBook': self._add_ebook() elif self._add_var.get() == 'Textbook': self._add_textbook() else: mb.showerror('Error : Type not selected', 'Please select a type.') def _update_book(self): """Update eBook attributes""" if self._update_var.get() == 'eBook': self._update_ebook() elif self._update_var.get() == 'Textbook': self._update_textbook() else: mb.showerror('Error : Type not selected', 'Please select a type.') def _update_ebook(self): """Update ebook attributes in the 'Book' database""" if not self._book_list.curselection(): mb.showerror('Error : Book not selected', 'Please select a book.') else: selected_index = self._book_list.curselection()[0] book_id = self._book_list.get(selected_index) r = requests.get( f"http://localhost:5000/library_manager/book/{book_id}") if r.json()['type'] != 'ebook': mb.showerror('Error : Invalid selection', 'Please select an ebook ID.') else: self._popup_win = tk.Toplevel() self._popup = UpdateeBookPopup(self._popup_win, book_id, self._close_book_cb) self._update_book_list() def _update_textbook(self): """Update textbook attributes in the 'Book' database""" if not self._book_list.curselection(): mb.showerror('Error : Book not selected', 'Please select a book.') else: self._popup_win = tk.Toplevel() selected_index = self._book_list.curselection()[0] book_id = self._book_list.get(selected_index) r = requests.get( f"http://localhost:5000/library_manager/book/{book_id}") if r.json()['type'] != 'textbook': mb.showerror('Error : Invalid selection', 'Please select a textbook ID.') else: self._popup = UpdateTextbookPopup(self._popup_win, book_id, self._close_book_cb) self._update_book_list() def _delete_book(self): """ Delete book Popup """ self._popup_win = tk.Toplevel() self._popup = DeleteBook(self._popup_win, self._close_book_cb) def _close_book_cb(self): """ Close Popup """ self._popup_win.destroy() self._update_book_list() def _quit_callback(self): """ Quit """ self.quit()
class Searcher(Frame): """ Keyword Searcher This is a very simple python program, which is designed for finding specified key-word in files. Just for fun! """ def __init__(self, master=None, cnf={}, **kwargs): super(Searcher, self).__init__(master, cnf, **kwargs) self._root_path_var = StringVar() self._keyword_var = StringVar(self) self._listbox = None self._result_queue = None self.pack(fill=BOTH, expand=YES, padx=5, pady=5) self.make_widgets() self._consumer() # config for main window self.master.title('Keyword Searcher') def make_widgets(self): frm1 = Frame(self) frm1.pack(side=TOP, fill=X) Entry(frm1, textvariable=self._root_path_var, font=DEFAULT_FONT).pack(side=LEFT, fill=X, expand=YES) Button(frm1, text='Add directory', font=DEFAULT_FONT, command=lambda: self._root_path_var.set(askdirectory(title='Add directory'))).pack(side=RIGHT) frm2 = Frame(self) frm2.pack(side=TOP, fill=X) keyword_ent = Entry(frm2, textvariable=self._keyword_var, font=DEFAULT_FONT) keyword_ent.pack(side=LEFT, fill=X, expand=YES) Button(frm2, text='Find', font=DEFAULT_FONT, command=self.find).pack(side=RIGHT) vs = Scrollbar(self) hs = Scrollbar(self) self._listbox = Listbox(self) vs.pack(side=RIGHT, fill=Y) vs.config(command=self._listbox.yview) hs.pack(side=BOTTOM, fill=X) hs.config(command=self._listbox.xview, orient='horizontal') self._listbox.config(yscrollcommand=vs.set, xscrollcommand=hs.set, font=DEFAULT_FONT) self._listbox.pack(fill=BOTH, expand=YES) self._listbox.bind('<Double-1>', self._navigate_to) def find(self): self._result_queue = queue.Queue() self._listbox.delete('0', 'end') Thread(target=self._find, args=(self._root_path_var.get(), self._keyword_var.get()), daemon=True).start() def _find(self, path, keyword): if not os.path.exists(path): return None for this_dir, sub_dirs, files in os.walk(path): for file in files: file_type = guess_type(file)[0] if file_type and 'text' in file_type: fp = os.path.join(this_dir, file) self._result_queue.put(fp) if keyword in open(fp).read() else None def _consumer(self): if self._result_queue: try: fp = self._result_queue.get(block=False) except queue.Empty: pass else: self._listbox.insert('end', fp) # auto scroll. self._listbox.yview('end') self.after(100, self._consumer) def _navigate_to(self, event): """ Only works on Ubuntu platform currently. Double click to navigate to selected path. It's a very convenient function. :return: None """ print(event) # get active item from listbox path = self._listbox.get('active') print(path) # open nautilus with param path, before that, check your platform. if 'ubuntu' in (os.popen('uname -a').read()).lower(): os.system('/usr/bin/nautilus {}'.format(path)) else: pass
class RecursiveDescentApp(object): """ A graphical tool for exploring the recursive descent parser. The tool displays the parser's tree and the remaining text, and allows the user to control the parser's operation. In particular, the user can expand subtrees on the frontier, match tokens on the frontier against the text, and backtrack. A "step" button simply steps through the parsing process, performing the operations that ``RecursiveDescentParser`` would use. """ def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingRecursiveDescentParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Recursive Descent Parser Application') # Set up key bindings. self._init_bindings() # Initialize the fonts. self._init_fonts(self._top) # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animation_frames = IntVar(self._top) self._animation_frames.set(5) self._animating_lock = 0 self._autostep = 0 # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # Initialize the parser. self._parser.initialize(self._sent) # Resize callback self._canvas.bind('<Configure>', self._configure) ######################################### ## Initialization Helpers ######################################### def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = tkinter.font.Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = tkinter.font.Font(family='helvetica', weight='bold', size=self._size.get()) self._font = tkinter.font.Font(family='helvetica', size=self._size.get()) if self._size.get() < 0: big = self._size.get()-2 else: big = self._size.get()+2 self._bigfont = tkinter.font.Font(family='helvetica', weight='bold', size=big) def _init_grammar(self, parent): # Grammar view. self._prodframe = listframe = Frame(parent) self._prodframe.pack(fill='both', side='left', padx=2) self._prodlist_label = Label(self._prodframe, font=self._boldfont, text='Available Expansions') self._prodlist_label.pack() self._prodlist = Listbox(self._prodframe, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0') self._prodlist.pack(side='right', fill='both', expand=1) self._productions = list(self._parser.grammar().productions()) for production in self._productions: self._prodlist.insert('end', (' %s' % production)) self._prodlist.config(height=min(len(self._productions), 25)) # Add a scrollbar if there are more than 25 productions. if len(self._productions) > 25: listscroll = Scrollbar(self._prodframe, orient='vertical') self._prodlist.config(yscrollcommand = listscroll.set) listscroll.config(command=self._prodlist.yview) listscroll.pack(side='left', fill='y') # If they select a production, apply it. self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select) def _init_bindings(self): # Key bindings are a good thing. self._top.bind('<Control-q>', self.destroy) self._top.bind('<Control-x>', self.destroy) self._top.bind('<Escape>', self.destroy) self._top.bind('e', self.expand) #self._top.bind('<Alt-e>', self.expand) #self._top.bind('<Control-e>', self.expand) self._top.bind('m', self.match) self._top.bind('<Alt-m>', self.match) self._top.bind('<Control-m>', self.match) self._top.bind('b', self.backtrack) self._top.bind('<Alt-b>', self.backtrack) self._top.bind('<Control-b>', self.backtrack) self._top.bind('<Control-z>', self.backtrack) self._top.bind('<BackSpace>', self.backtrack) self._top.bind('a', self.autostep) #self._top.bind('<Control-a>', self.autostep) self._top.bind('<Control-space>', self.autostep) self._top.bind('<Control-c>', self.cancel_autostep) self._top.bind('<space>', self.step) self._top.bind('<Delete>', self.reset) self._top.bind('<Control-p>', self.postscript) #self._top.bind('<h>', self.help) #self._top.bind('<Alt-h>', self.help) self._top.bind('<Control-h>', self.help) self._top.bind('<F1>', self.help) #self._top.bind('<g>', self.toggle_grammar) #self._top.bind('<Alt-g>', self.toggle_grammar) #self._top.bind('<Control-g>', self.toggle_grammar) self._top.bind('<Control-g>', self.edit_grammar) self._top.bind('<Control-t>', self.edit_sentence) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill='none', side='bottom', padx=3, pady=2) Button(buttonframe, text='Step', background='#90c0d0', foreground='black', command=self.step,).pack(side='left') Button(buttonframe, text='Autostep', background='#90c0d0', foreground='black', command=self.autostep,).pack(side='left') Button(buttonframe, text='Expand', underline=0, background='#90f090', foreground='black', command=self.expand).pack(side='left') Button(buttonframe, text='Match', underline=0, background='#90f090', foreground='black', command=self.match).pack(side='left') Button(buttonframe, text='Backtrack', underline=0, background='#f0a0a0', foreground='black', command=self.backtrack).pack(side='left') # Replace autostep... # self._autostep_button = Button(buttonframe, text='Autostep', # underline=0, command=self.autostep) # self._autostep_button.pack(side='left') def _configure(self, event): self._autostep = 0 (x1, y1, x2, y2) = self._cframe.scrollregion() y2 = event.height - 6 self._canvas['scrollregion'] = '%d %d %d %d' % (x1,y1,x2,y2) self._redraw() def _init_feedback(self, parent): self._feedbackframe = feedbackframe = Frame(parent) feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3) self._lastoper_label = Label(feedbackframe, text='Last Operation:', font=self._font) self._lastoper_label.pack(side='left') lastoperframe = Frame(feedbackframe, relief='sunken', border=1) lastoperframe.pack(fill='x', side='right', expand=1, padx=5) self._lastoper1 = Label(lastoperframe, foreground='#007070', background='#f0f0f0', font=self._font) self._lastoper2 = Label(lastoperframe, anchor='w', width=30, foreground='#004040', background='#f0f0f0', font=self._font) self._lastoper1.pack(side='left') self._lastoper2.pack(side='left', fill='x', expand=1) def _init_canvas(self, parent): self._cframe = CanvasFrame(parent, background='white', #width=525, height=250, closeenough=10, border=2, relief='sunken') self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() # Initially, there's no tree or text self._tree = None self._textwidgets = [] self._textline = None def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Reset Parser', underline=0, command=self.reset, accelerator='Del') filemenu.add_command(label='Print to Postscript', underline=0, command=self.postscript, accelerator='Ctrl-p') filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label='Edit Grammar', underline=5, command=self.edit_grammar, accelerator='Ctrl-g') editmenu.add_command(label='Edit Text', underline=5, command=self.edit_sentence, accelerator='Ctrl-t') menubar.add_cascade(label='Edit', underline=0, menu=editmenu) rulemenu = Menu(menubar, tearoff=0) rulemenu.add_command(label='Step', underline=1, command=self.step, accelerator='Space') rulemenu.add_separator() rulemenu.add_command(label='Match', underline=0, command=self.match, accelerator='Ctrl-m') rulemenu.add_command(label='Expand', underline=0, command=self.expand, accelerator='Ctrl-e') rulemenu.add_separator() rulemenu.add_command(label='Backtrack', underline=0, command=self.backtrack, accelerator='Ctrl-b') menubar.add_cascade(label='Apply', underline=0, menu=rulemenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_checkbutton(label="Show Grammar", underline=0, variable=self._show_grammar, command=self._toggle_grammar) viewmenu.add_separator() viewmenu.add_radiobutton(label='Tiny', variable=self._size, underline=0, value=10, command=self.resize) viewmenu.add_radiobutton(label='Small', variable=self._size, underline=0, value=12, command=self.resize) viewmenu.add_radiobutton(label='Medium', variable=self._size, underline=0, value=14, command=self.resize) viewmenu.add_radiobutton(label='Large', variable=self._size, underline=0, value=18, command=self.resize) viewmenu.add_radiobutton(label='Huge', variable=self._size, underline=0, value=24, command=self.resize) menubar.add_cascade(label='View', underline=0, menu=viewmenu) animatemenu = Menu(menubar, tearoff=0) animatemenu.add_radiobutton(label="No Animation", underline=0, variable=self._animation_frames, value=0) animatemenu.add_radiobutton(label="Slow Animation", underline=0, variable=self._animation_frames, value=10, accelerator='-') animatemenu.add_radiobutton(label="Normal Animation", underline=0, variable=self._animation_frames, value=5, accelerator='=') animatemenu.add_radiobutton(label="Fast Animation", underline=0, variable=self._animation_frames, value=2, accelerator='+') menubar.add_cascade(label="Animate", underline=1, menu=animatemenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label='About', underline=0, command=self.about) helpmenu.add_command(label='Instructions', underline=0, command=self.help, accelerator='F1') menubar.add_cascade(label='Help', underline=0, menu=helpmenu) parent.config(menu=menubar) ######################################### ## Helper ######################################### def _get(self, widget, treeloc): for i in treeloc: widget = widget.subtrees()[i] if isinstance(widget, TreeSegmentWidget): widget = widget.label() return widget ######################################### ## Main draw procedure ######################################### def _redraw(self): canvas = self._canvas # Delete the old tree, widgets, etc. if self._tree is not None: self._cframe.destroy_widget(self._tree) for twidget in self._textwidgets: self._cframe.destroy_widget(twidget) if self._textline is not None: self._canvas.delete(self._textline) # Draw the tree. helv = ('helvetica', -self._size.get()) bold = ('helvetica', -self._size.get(), 'bold') attribs = {'tree_color': '#000000', 'tree_width': 2, 'node_font': bold, 'leaf_font': helv,} tree = self._parser.tree() self._tree = tree_to_treesegment(canvas, tree, **attribs) self._cframe.add_widget(self._tree, 30, 5) # Draw the text. helv = ('helvetica', -self._size.get()) bottom = y = self._cframe.scrollregion()[3] self._textwidgets = [TextWidget(canvas, word, font=self._font) for word in self._sent] for twidget in self._textwidgets: self._cframe.add_widget(twidget, 0, 0) twidget.move(0, bottom-twidget.bbox()[3]-5) y = min(y, twidget.bbox()[1]) # Draw a line over the text, to separate it from the tree. self._textline = canvas.create_line(-5000, y-5, 5000, y-5, dash='.') # Highlight appropriate nodes. self._highlight_nodes() self._highlight_prodlist() # Make sure the text lines up. self._position_text() def _redraw_quick(self): # This should be more-or-less sufficient after an animation. self._highlight_nodes() self._highlight_prodlist() self._position_text() def _highlight_nodes(self): # Highlight the list of nodes to be checked. bold = ('helvetica', -self._size.get(), 'bold') for treeloc in self._parser.frontier()[:1]: self._get(self._tree, treeloc)['color'] = '#20a050' self._get(self._tree, treeloc)['font'] = bold for treeloc in self._parser.frontier()[1:]: self._get(self._tree, treeloc)['color'] = '#008080' def _highlight_prodlist(self): # Highlight the productions that can be expanded. # Boy, too bad tkinter doesn't implement Listbox.itemconfig; # that would be pretty useful here. self._prodlist.delete(0, 'end') expandable = self._parser.expandable_productions() untried = self._parser.untried_expandable_productions() productions = self._productions for index in range(len(productions)): if productions[index] in expandable: if productions[index] in untried: self._prodlist.insert(index, ' %s' % productions[index]) else: self._prodlist.insert(index, ' %s (TRIED)' % productions[index]) self._prodlist.selection_set(index) else: self._prodlist.insert(index, ' %s' % productions[index]) def _position_text(self): # Line up the text widgets that are matched against the tree numwords = len(self._sent) num_matched = numwords - len(self._parser.remaining_text()) leaves = self._tree_leaves()[:num_matched] xmax = self._tree.bbox()[0] for i in range(0, len(leaves)): widget = self._textwidgets[i] leaf = leaves[i] widget['color'] = '#006040' leaf['color'] = '#006040' widget.move(leaf.bbox()[0] - widget.bbox()[0], 0) xmax = widget.bbox()[2] + 10 # Line up the text widgets that are not matched against the tree. for i in range(len(leaves), numwords): widget = self._textwidgets[i] widget['color'] = '#a0a0a0' widget.move(xmax - widget.bbox()[0], 0) xmax = widget.bbox()[2] + 10 # If we have a complete parse, make everything green :) if self._parser.currently_complete(): for twidget in self._textwidgets: twidget['color'] = '#00a000' # Move the matched leaves down to the text. for i in range(0, len(leaves)): widget = self._textwidgets[i] leaf = leaves[i] dy = widget.bbox()[1] - leaf.bbox()[3] - 10.0 dy = max(dy, leaf.parent().label().bbox()[3] - leaf.bbox()[3] + 10) leaf.move(0, dy) def _tree_leaves(self, tree=None): if tree is None: tree = self._tree if isinstance(tree, TreeSegmentWidget): leaves = [] for child in tree.subtrees(): leaves += self._tree_leaves(child) return leaves else: return [tree] ######################################### ## Button Callbacks ######################################### def destroy(self, *e): self._autostep = 0 if self._top is None: return self._top.destroy() self._top = None def reset(self, *e): self._autostep = 0 self._parser.initialize(self._sent) self._lastoper1['text'] = 'Reset Application' self._lastoper2['text'] = '' self._redraw() def autostep(self, *e): if self._animation_frames.get() == 0: self._animation_frames.set(2) if self._autostep: self._autostep = 0 else: self._autostep = 1 self._step() def cancel_autostep(self, *e): #self._autostep_button['text'] = 'Autostep' self._autostep = 0 # Make sure to stop auto-stepping if we get any user input. def step(self, *e): self._autostep = 0; self._step() def match(self, *e): self._autostep = 0; self._match() def expand(self, *e): self._autostep = 0; self._expand() def backtrack(self, *e): self._autostep = 0; self._backtrack() def _step(self): if self._animating_lock: return # Try expanding, matching, and backtracking (in that order) if self._expand(): pass elif self._parser.untried_match() and self._match(): pass elif self._backtrack(): pass else: self._lastoper1['text'] = 'Finished' self._lastoper2['text'] = '' self._autostep = 0 # Check if we just completed a parse. if self._parser.currently_complete(): self._autostep = 0 self._lastoper2['text'] += ' [COMPLETE PARSE]' def _expand(self, *e): if self._animating_lock: return old_frontier = self._parser.frontier() rv = self._parser.expand() if rv is not None: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = rv self._prodlist.selection_clear(0, 'end') index = self._productions.index(rv) self._prodlist.selection_set(index) self._animate_expand(old_frontier[0]) return 1 else: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = '(all expansions tried)' return 0 def _match(self, *e): if self._animating_lock: return old_frontier = self._parser.frontier() rv = self._parser.match() if rv is not None: self._lastoper1['text'] = 'Match:' self._lastoper2['text'] = rv self._animate_match(old_frontier[0]) return 1 else: self._lastoper1['text'] = 'Match:' self._lastoper2['text'] = '(failed)' return 0 def _backtrack(self, *e): if self._animating_lock: return if self._parser.backtrack(): elt = self._parser.tree() for i in self._parser.frontier()[0]: elt = elt[i] self._lastoper1['text'] = 'Backtrack' self._lastoper2['text'] = '' if isinstance(elt, Tree): self._animate_backtrack(self._parser.frontier()[0]) else: self._animate_match_backtrack(self._parser.frontier()[0]) return 1 else: self._autostep = 0 self._lastoper1['text'] = 'Finished' self._lastoper2['text'] = '' return 0 def about(self, *e): ABOUT = ("NLTK Recursive Descent Parser Application\n"+ "Written by Edward Loper") TITLE = 'About: Recursive Descent Parser Application' try: from tkinter.messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def help(self, *e): self._autostep = 0 # The default font's not very legible; try using 'fixed' instead. try: ShowText(self._top, 'Help: Recursive Descent Parser Application', (__doc__ or '').strip(), width=75, font='fixed') except: ShowText(self._top, 'Help: Recursive Descent Parser Application', (__doc__ or '').strip(), width=75) def postscript(self, *e): self._autostep = 0 self._cframe.print_to_file() def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs) def resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) self._bigfont.configure(size=-(abs(size+2))) self._redraw() ######################################### ## Expand Production Selection ######################################### def _toggle_grammar(self, *e): if self._show_grammar.get(): self._prodframe.pack(fill='both', side='left', padx=2, after=self._feedbackframe) self._lastoper1['text'] = 'Show Grammar' else: self._prodframe.pack_forget() self._lastoper1['text'] = 'Hide Grammar' self._lastoper2['text'] = '' # def toggle_grammar(self, *e): # self._show_grammar = not self._show_grammar # if self._show_grammar: # self._prodframe.pack(fill='both', expand='y', side='left', # after=self._feedbackframe) # self._lastoper1['text'] = 'Show Grammar' # else: # self._prodframe.pack_forget() # self._lastoper1['text'] = 'Hide Grammar' # self._lastoper2['text'] = '' def _prodlist_select(self, event): selection = self._prodlist.curselection() if len(selection) != 1: return index = int(selection[0]) old_frontier = self._parser.frontier() production = self._parser.expand(self._productions[index]) if production: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = production self._prodlist.selection_clear(0, 'end') self._prodlist.selection_set(index) self._animate_expand(old_frontier[0]) else: # Reset the production selections. self._prodlist.selection_clear(0, 'end') for prod in self._parser.expandable_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) ######################################### ## Animation ######################################### def _animate_expand(self, treeloc): oldwidget = self._get(self._tree, treeloc) oldtree = oldwidget.parent() top = not isinstance(oldtree.parent(), TreeSegmentWidget) tree = self._parser.tree() for i in treeloc: tree = tree[i] widget = tree_to_treesegment(self._canvas, tree, node_font=self._boldfont, leaf_color='white', tree_width=2, tree_color='white', node_color='white', leaf_font=self._font) widget.label()['color'] = '#20a050' (oldx, oldy) = oldtree.label().bbox()[:2] (newx, newy) = widget.label().bbox()[:2] widget.move(oldx-newx, oldy-newy) if top: self._cframe.add_widget(widget, 0, 5) widget.move(30-widget.label().bbox()[0], 0) self._tree = widget else: oldtree.parent().replace_child(oldtree, widget) # Move the children over so they don't overlap. # Line the children up in a strange way. if widget.subtrees(): dx = (oldx + widget.label().width()/2 - widget.subtrees()[0].bbox()[0]/2 - widget.subtrees()[0].bbox()[2]/2) for subtree in widget.subtrees(): subtree.move(dx, 0) self._makeroom(widget) if top: self._cframe.destroy_widget(oldtree) else: oldtree.destroy() colors = ['gray%d' % (10*int(10*x/self._animation_frames.get())) for x in range(self._animation_frames.get(),0,-1)] # Move the text string down, if necessary. dy = widget.bbox()[3] + 30 - self._canvas.coords(self._textline)[1] if dy > 0: for twidget in self._textwidgets: twidget.move(0, dy) self._canvas.move(self._textline, 0, dy) self._animate_expand_frame(widget, colors) def _makeroom(self, treeseg): """ Make sure that no sibling tree bbox's overlap. """ parent = treeseg.parent() if not isinstance(parent, TreeSegmentWidget): return index = parent.subtrees().index(treeseg) # Handle siblings to the right rsiblings = parent.subtrees()[index+1:] if rsiblings: dx = treeseg.bbox()[2] - rsiblings[0].bbox()[0] + 10 for sibling in rsiblings: sibling.move(dx, 0) # Handle siblings to the left if index > 0: lsibling = parent.subtrees()[index-1] dx = max(0, lsibling.bbox()[2] - treeseg.bbox()[0] + 10) treeseg.move(dx, 0) # Keep working up the tree. self._makeroom(parent) def _animate_expand_frame(self, widget, colors): if len(colors) > 0: self._animating_lock = 1 widget['color'] = colors[0] for subtree in widget.subtrees(): if isinstance(subtree, TreeSegmentWidget): subtree.label()['color'] = colors[0] else: subtree['color'] = colors[0] self._top.after(50, self._animate_expand_frame, widget, colors[1:]) else: widget['color'] = 'black' for subtree in widget.subtrees(): if isinstance(subtree, TreeSegmentWidget): subtree.label()['color'] = 'black' else: subtree['color'] = 'black' self._redraw_quick() widget.label()['color'] = 'black' self._animating_lock = 0 if self._autostep: self._step() def _animate_backtrack(self, treeloc): # Flash red first, if we're animating. if self._animation_frames.get() == 0: colors = [] else: colors = ['#a00000', '#000000', '#a00000'] colors += ['gray%d' % (10*int(10*x/(self._animation_frames.get()))) for x in range(1, self._animation_frames.get()+1)] widgets = [self._get(self._tree, treeloc).parent()] for subtree in widgets[0].subtrees(): if isinstance(subtree, TreeSegmentWidget): widgets.append(subtree.label()) else: widgets.append(subtree) self._animate_backtrack_frame(widgets, colors) def _animate_backtrack_frame(self, widgets, colors): if len(colors) > 0: self._animating_lock = 1 for widget in widgets: widget['color'] = colors[0] self._top.after(50, self._animate_backtrack_frame, widgets, colors[1:]) else: for widget in widgets[0].subtrees(): widgets[0].remove_child(widget) widget.destroy() self._redraw_quick() self._animating_lock = 0 if self._autostep: self._step() def _animate_match_backtrack(self, treeloc): widget = self._get(self._tree, treeloc) node = widget.parent().label() dy = (1.0 * (node.bbox()[3] - widget.bbox()[1] + 14) / max(1, self._animation_frames.get())) self._animate_match_backtrack_frame(self._animation_frames.get(), widget, dy) def _animate_match(self, treeloc): widget = self._get(self._tree, treeloc) dy = ((self._textwidgets[0].bbox()[1] - widget.bbox()[3] - 10.0) / max(1, self._animation_frames.get())) self._animate_match_frame(self._animation_frames.get(), widget, dy) def _animate_match_frame(self, frame, widget, dy): if frame > 0: self._animating_lock = 1 widget.move(0, dy) self._top.after(10, self._animate_match_frame, frame-1, widget, dy) else: widget['color'] = '#006040' self._redraw_quick() self._animating_lock = 0 if self._autostep: self._step() def _animate_match_backtrack_frame(self, frame, widget, dy): if frame > 0: self._animating_lock = 1 widget.move(0, dy) self._top.after(10, self._animate_match_backtrack_frame, frame-1, widget, dy) else: widget.parent().remove_child(widget) widget.destroy() self._animating_lock = 0 if self._autostep: self._step() def edit_grammar(self, *e): CFGEditor(self._top, self._parser.grammar(), self.set_grammar) def set_grammar(self, grammar): self._parser.set_grammar(grammar) self._productions = list(grammar.productions()) self._prodlist.delete(0, 'end') for production in self._productions: self._prodlist.insert('end', (' %s' % production)) def edit_sentence(self, *e): sentence = " ".join(self._sent) title = 'Edit Text' instr = 'Enter a new sentence to parse.' EntryDialog(self._top, sentence, instr, self.set_sentence, title) def set_sentence(self, sentence): self._sent = sentence.split() #[XX] use tagged? self.reset()
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)