def doGUI(self, hostname=None): self.master = Tk() self.master.title('Blessclient - MFA') textmsg = 'Enter your AWS MFA code: ' if hostname: textmsg = 'Enter your AWS MFA code to connect to {}: '.format( hostname) Label(self.master, text=textmsg).grid(row=0) self.e1 = Entry(self.master) self.e1.grid(row=0, column=1, padx=4) Button(self.master, text='OK', command=self.show_entry_fields, default=ACTIVE).grid(row=3, column=0, sticky=W, pady=4) Button(self.master, text='Cancel', command=self.quit).grid(row=3, column=1, sticky=W, pady=4) self.center() self.master.bind('<Return>', self.show_entry_fields) self.master.lift() self.master.attributes('-topmost', True) self.master.focus_force() self.e1.focus_set() if platform.system() == 'Darwin': # Hack to get the GUI dialog focused in OSX os.system( '/usr/bin/osascript -e \'tell app "Finder" to set frontmost of process "python" to true\'' ) mainloop()
def _init_startframe(self): frame = self._startframe = Frame(self._top) self._start = Entry(frame) self._start.pack(side="right") Label(frame, text="Start Symbol:").pack(side="right") Label(frame, text="Productions:").pack(side="left") self._start.insert(0, self._cfg.start().symbol())
def _init_startframe(self): frame = self._startframe = Frame(self._top) self._start = Entry(frame) self._start.pack(side='right') Label(frame, text='Start Symbol:').pack(side='right') Label(frame, text='Productions:').pack(side='left') self._start.insert(0, self._cfg.start().symbol())
def doGUI(self, hostname=None): self.master = Tk() self.master.title('Blessclient - MFA') textmsg = 'Enter your AWS MFA code: ' if hostname: textmsg = 'Enter your AWS MFA code to connect to {}: '.format( hostname) Label(self.master, text=textmsg).grid(row=0) self.e1 = Entry(self.master) self.e1.grid(row=0, column=1, padx=4) Button(self.master, text='OK', command=self.show_entry_fields, default=ACTIVE).grid(row=3, column=0, sticky=W, pady=4) Button(self.master, text='Cancel', command=self.quit).grid(row=3, column=1, sticky=W, pady=4) self.center() self.master.bind('<Return>', self.show_entry_fields) self.master.lift() self.master.attributes('-topmost', True) self.master.focus_force() self.e1.focus_set() if platform.system() == 'Darwin': # Hack to get the GUI dialog focused in OSX # https://stackoverflow.com/questions/1892339/how-to-make-a-tkinter-window-jump-to-the-front/37235492#37235492 tmpl = 'tell application "System Events" to set frontmost of every process whose unix id is {} to true' script = tmpl.format(os.getpid()) subprocess.check_call(['/usr/bin/osascript', '-e', script]) mainloop()
def _init_query_box(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) another = Frame(innerframe, background=self._BACKGROUND_COLOUR) self.query_box = Entry(another, width=60) self.query_box.pack(side='left', fill='x', pady=25, anchor='center') self.search_button = Button(another, text='Search', command=self.search, borderwidth=1, highlightthickness=1) self.search_button.pack(side='left', fill='x', pady=25, anchor='center') self.query_box.bind('<KeyPress-Return>', self.search_enter_keypress_handler) another.pack() innerframe.pack(side='top', fill='x', anchor='n')
class TokenInputGUI(object): def show_entry_fields(self, event=None): self.code = self.e1.get() self.master.withdraw() self.master.quit() def quit(self): self.master.quit() self.code = None def doGUI(self, hostname=None): self.master = Tk() self.master.title('Blessclient - MFA') textmsg = 'Enter your AWS MFA code: ' if hostname: textmsg = 'Enter your AWS MFA code to connect to {}: '.format( hostname) Label(self.master, text=textmsg).grid(row=0) self.e1 = Entry(self.master) self.e1.grid(row=0, column=1, padx=4) Button(self.master, text='OK', command=self.show_entry_fields, default=ACTIVE).grid(row=3, column=0, sticky=W, pady=4) Button(self.master, text='Cancel', command=self.quit).grid(row=3, column=1, sticky=W, pady=4) self.center() self.master.bind('<Return>', self.show_entry_fields) self.master.lift() self.master.attributes('-topmost', True) self.master.focus_force() self.e1.focus_set() if platform.system() == 'Darwin': # Hack to get the GUI dialog focused in OSX # https://stackoverflow.com/questions/1892339/how-to-make-a-tkinter-window-jump-to-the-front/37235492#37235492 tmpl = 'tell application "System Events" to set frontmost of every process whose unix id is {} to true' script = tmpl.format(os.getpid()) subprocess.check_call(['/usr/bin/osascript', '-e', script]) mainloop() # http://stackoverflow.com/questions/3352918/how-to-center-a-window-on-the-screen-in-tkinter def center(self): self.master.update_idletasks() w = self.master.winfo_screenwidth() h = self.master.winfo_screenheight() size = tuple( int(_) for _ in self.master.geometry().split('+')[0].split('x')) x = w / 2 - size[0] / 2 y = h / 2 - size[1] / 2 self.master.geometry("%dx%d+%d+%d" % (size + (x, y)))
class InputDialog(_TkDialog): def __init__(self, message, default='', hidden=False): _TkDialog.__init__(self, message, default, hidden=hidden) def _create_selector(self, parent, default, hidden): self._entry = Entry(parent, show='*' if hidden else '') self._entry.insert(0, default) self._entry.select_range(0, END) return self._entry def _get_value(self): return self._entry.get()
def __create_content(self): self.__rootFrame = TKTk() self.__rootFrame.withdraw() self.__top = TKToplevel(self.__rootFrame) self.__top.title("Login") self.__top.protocol("WM_DELETE_WINDOW", self.__rootFrame.destroy) self.__top.bind('<Return>', self.__enter_action) self.__top.update_idletasks() width = self.__top.winfo_width() height = self.__top.winfo_height() x = (self.__top.winfo_screenwidth() // 2) - (width // 2) y = (self.__top.winfo_screenheight() // 2) - (height // 2) self.__top.geometry("+%d+%d" % (x, y)) row = 0 expLabel = TKLabel(self.__top, text='Login to host:') expLabel.grid(row=row, column=0, columnspan=4, padx=5, pady=2) row = row + 1 urlLabel = TKLabel(self.__top, text=self.__host) urlLabel.grid(row=row, column=0, columnspan=4, padx=5, pady=2) row = row + 1 usrLabel = TKLabel(self.__top, text='User') usrLabel.grid(row=row, column=0, columnspan=2, padx=20, pady=5) self.__usrEntry = TKEntry(self.__top, width=20) self.__usrEntry.grid(row=row, column=2, columnspan=2, padx=5, pady=5) row = row + 1 pwdLabel = TKLabel(self.__top, text='Password') pwdLabel.grid(row=row, column=0, columnspan=2, padx=20, pady=5) self.__pwdEntry = TKEntry(self.__top, width=20, show="*") self.__pwdEntry.grid(row=row, column=2, columnspan=2, padx=5, pady=5) row = row + 1 cancelButton = TKButton(self.__top, text='Cancel', command=self.__cancel_action) cancelButton.grid(row=row, column=1, padx=5, pady=5) loginButton = TKButton(self.__top, text='Login', command=self.__login_action) loginButton.grid(row=row, column=2, padx=5, pady=5)
def __create_content(self): self.__rootFrame = TKTk() self.__rootFrame.withdraw() self.__top = TKToplevel(self.__rootFrame) self.__top.title("Login") self.__top.protocol("WM_DELETE_WINDOW", self.__rootFrame.destroy) self.__top.bind('<Return>', self.__enter_action) self.__top.update_idletasks() width = self.__top.winfo_width() height = self.__top.winfo_height() x = (self.__top.winfo_screenwidth() // 2) - (width // 2) y = (self.__top.winfo_screenheight() // 2) - (height // 2) self.__top.geometry("+%d+%d" % (x, y)) row = 0 expLabel = TKLabel(self.__top, text='Login to host:') expLabel.grid(row=row, column=0, columnspan=4, padx=5, pady=2) row = row+1 urlLabel = TKLabel(self.__top, text=self.__host) urlLabel.grid(row=row, column=0, columnspan=4, padx=5, pady=2) row = row+1 usrLabel = TKLabel(self.__top, text='User') usrLabel.grid(row=row, column=0, columnspan=2, padx=20, pady=5) self.__usrEntry = TKEntry(self.__top, width=20) self.__usrEntry.grid(row=row, column=2, columnspan=2, padx=5, pady=5) row = row+1 pwdLabel = TKLabel(self.__top, text='Password') pwdLabel.grid(row=row, column=0, columnspan=2, padx=20, pady=5) self.__pwdEntry = TKEntry(self.__top, width=20, show="*") self.__pwdEntry.grid(row=row, column=2, columnspan=2, padx=5, pady=5) row = row+1 cancelButton = TKButton(self.__top, text='Cancel', command=self.__cancel_action) cancelButton.grid(row=row, column=1, padx=5, pady=5) loginButton = TKButton(self.__top, text='Login', command=self.__login_action) loginButton.grid(row=row, column=2, padx=5, pady=5)
def _init_query_box(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) another = Frame(innerframe, background=self._BACKGROUND_COLOUR) self.query_box = Entry(another, width=60) self.query_box.pack(side="left", fill="x", pady=25, anchor="center") self.search_button = Button( another, text="Search", command=self.search, borderwidth=1, highlightthickness=1, ) self.search_button.pack(side="left", fill="x", pady=25, anchor="center") self.query_box.bind("<KeyPress-Return>", self.search_enter_keypress_handler) another.pack() innerframe.pack(side="top", fill="x", anchor="n")
def __init__(self, parent, app): parent.title('Auth window') self.parent = parent self.root = app # Widget Initialization self._label_header = Label( parent, font="{Segoe UI} 20 bold", foreground="#ff0000", text="Trakt Account Authorization", ) self._button_get_code = Button( parent, font="{MS Sans Serif} 12 bold", text="Get PIN Code", ) self._label_enter_code = Label( parent, font="{MS Sans Serif} 14", text="Enter the code:", ) self._label_click = Label( parent, font="{MS Sans Serif} 14", text="Click the button to get a code:", ) self.pin_code = StringVar() self._entry_code = Entry( parent, font="{MS Sans Serif} 14 bold", width=10, justify="center", textvariable=self.pin_code, state="disabled", ) self._button_done = Button( parent, borderwidth=3, font="{MS Sans Serif} 12 bold", text="Done", state="disabled", ) # widget commands self._button_get_code.configure(command=self.button_get_code_command) self._button_done.configure(command=self.button_done_command) # Geometry Management self._label_header.grid(in_=parent, column=1, row=1, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="ew") self._label_click.grid(in_=parent, column=1, row=2, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") self._button_get_code.grid(in_=parent, column=1, row=3, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") self._label_enter_code.grid(in_=parent, column=1, row=4, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") self._entry_code.grid(in_=parent, column=1, row=5, columnspan=1, ipadx=5, ipady=0, padx=5, pady=0, rowspan=1, sticky="") self._button_done.grid(in_=parent, column=1, row=6, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") # Resize Behavior parent.resizable(False, False) parent.grid_rowconfigure(1, weight=1, minsize=40, pad=10) parent.grid_rowconfigure(2, weight=1, minsize=40, pad=10) parent.grid_rowconfigure(3, weight=1, minsize=40, pad=10) parent.grid_rowconfigure(4, weight=1, minsize=40, pad=10) parent.grid_rowconfigure(5, weight=1, minsize=50, pad=10) parent.grid_rowconfigure(6, weight=1, minsize=50, pad=10) parent.grid_columnconfigure(1, weight=1, minsize=0, pad=10)
def init_gui(self): """init helper""" window = PanedWindow(self.root, orient="vertical") window.pack(side=TOP, fill=BOTH, expand=True) top_pane = Frame(window) window.add(top_pane) mid_pane = Frame(window) window.add(mid_pane) bottom_pane = Frame(window) window.add(bottom_pane) #setting up frames top_frame = Frame(top_pane) mid_frame = Frame(top_pane) history_frame = Frame(top_pane) radio_frame = Frame(mid_pane) rating_frame = Frame(mid_pane) res_frame = Frame(mid_pane) check_frame = Frame(bottom_pane) msg_frame = Frame(bottom_pane) btn_frame = Frame(bottom_pane) 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=X) rating_frame.pack(side=TOP, fill=X) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=X) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) # Binding F5 application-wide to run lint self.root.bind('<F5>', self.run_lint) #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.lb_messages = Listbox( msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white") self.lb_messages.bind("<Double-Button-1>", self.show_sourcefile) self.lb_messages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lb_messages.yview) bottomscrollbar.config(command=self.lb_messages.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) #labelbl_ratingls lbl_rating_label = Label(rating_frame, text='Rating:') lbl_rating_label.pack(side=LEFT) lbl_rating = Label(rating_frame, textvariable=self.rating) lbl_rating.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.txt_module = Entry(top_frame, background='white') self.txt_module.bind('<Return>', self.run_lint) self.txt_module.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) raw_met = 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) msg_cat = 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) source_file = Radiobutton( radio_frame, text="Source File", variable=self.box, value="Source File", command=self.refresh_results_window) report.select() report.grid(column=0, row=0, sticky=W) raw_met.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=W) stat.grid(column=0, row=1, sticky=W) msg_cat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, sticky=W) source_file.grid(column=3, row=1, 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.txt_module.focus_set()
def init_gui(self): """init helper""" window = PanedWindow(self.root, orient="vertical") window.pack(side=TOP, fill=BOTH, expand=True) top_pane = Frame(window) window.add(top_pane) mid_pane = Frame(window) window.add(mid_pane) bottom_pane = Frame(window) window.add(bottom_pane) #setting up frames top_frame = Frame(top_pane) mid_frame = Frame(top_pane) history_frame = Frame(top_pane) radio_frame = Frame(mid_pane) rating_frame = Frame(mid_pane) res_frame = Frame(mid_pane) check_frame = Frame(bottom_pane) msg_frame = Frame(bottom_pane) btn_frame = Frame(bottom_pane) 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=X) rating_frame.pack(side=TOP, fill=X) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=X) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) # Binding F5 application-wide to run lint self.root.bind('<F5>', self.run_lint) #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.lb_messages = Listbox(msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white") self.lb_messages.bind("<Double-Button-1>", self.show_sourcefile) self.lb_messages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lb_messages.yview) bottomscrollbar.config(command=self.lb_messages.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) #labelbl_ratingls lbl_rating_label = Label(rating_frame, text='Rating:') lbl_rating_label.pack(side=LEFT) lbl_rating = Label(rating_frame, textvariable=self.rating) lbl_rating.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.txt_module = Entry(top_frame, background='white') self.txt_module.bind('<Return>', self.run_lint) self.txt_module.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) raw_met = 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) msg_cat = 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) source_file = Radiobutton(radio_frame, text="Source File", variable=self.box, value="Source File", command=self.refresh_results_window) report.select() report.grid(column=0, row=0, sticky=W) raw_met.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=W) stat.grid(column=0, row=1, sticky=W) msg_cat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, sticky=W) source_file.grid(column=3, row=1, 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.txt_module.focus_set()
class LoginDialog(object): def __init__(self, host): self.__interna_init() self.__host = host self.__create_content() def __interna_init(self): self.__rootFrame = None self.__top = None self.__usrEntry = None self.__pwdEntry = None self.__accepted = False self.__host = None self.__usr = None self.__pwd = None def __cancel_action(self): self.__accepted = False self.__rootFrame.destroy() def __login_action(self): self.__accepted = True self.__usr = self.__usrEntry.get() self.__pwd = self.__pwdEntry.get() self.__rootFrame.destroy() def __enter_action(self, event): self.__login_action() def __create_content(self): self.__rootFrame = TKTk() self.__rootFrame.withdraw() self.__top = TKToplevel(self.__rootFrame) self.__top.title("Login") self.__top.protocol("WM_DELETE_WINDOW", self.__rootFrame.destroy) self.__top.bind('<Return>', self.__enter_action) self.__top.update_idletasks() width = self.__top.winfo_width() height = self.__top.winfo_height() x = (self.__top.winfo_screenwidth() // 2) - (width // 2) y = (self.__top.winfo_screenheight() // 2) - (height // 2) self.__top.geometry("+%d+%d" % (x, y)) row = 0 expLabel = TKLabel(self.__top, text='Login to host:') expLabel.grid(row=row, column=0, columnspan=4, padx=5, pady=2) row = row+1 urlLabel = TKLabel(self.__top, text=self.__host) urlLabel.grid(row=row, column=0, columnspan=4, padx=5, pady=2) row = row+1 usrLabel = TKLabel(self.__top, text='User') usrLabel.grid(row=row, column=0, columnspan=2, padx=20, pady=5) self.__usrEntry = TKEntry(self.__top, width=20) self.__usrEntry.grid(row=row, column=2, columnspan=2, padx=5, pady=5) row = row+1 pwdLabel = TKLabel(self.__top, text='Password') pwdLabel.grid(row=row, column=0, columnspan=2, padx=20, pady=5) self.__pwdEntry = TKEntry(self.__top, width=20, show="*") self.__pwdEntry.grid(row=row, column=2, columnspan=2, padx=5, pady=5) row = row+1 cancelButton = TKButton(self.__top, text='Cancel', command=self.__cancel_action) cancelButton.grid(row=row, column=1, padx=5, pady=5) loginButton = TKButton(self.__top, text='Login', command=self.__login_action) loginButton.grid(row=row, column=2, padx=5, pady=5) def show_login(self): self.__usrEntry.focus_set() self.__rootFrame.mainloop() def is_accepted(self): return self.__accepted def get_user(self): return self.__usr def get_password(self): return self.__pwd
def _create_selector(self, parent, default, hidden): self._entry = Entry(parent, show='*' if hidden else '') self._entry.insert(0, default) self._entry.select_range(0, END) return self._entry
def __init__(self, *args, **kw): Entry.__init__(self, *args, **kw) self.bind("<Control-Key>", self.ignore)
class ConcordanceSearchView(object): _BACKGROUND_COLOUR='#FFF' #white #Colour of highlighted results _HIGHLIGHT_WORD_COLOUR='#F00' #red _HIGHLIGHT_WORD_TAG='HL_WRD_TAG' _HIGHLIGHT_LABEL_COLOUR='#C0C0C0' # dark grey _HIGHLIGHT_LABEL_TAG='HL_LBL_TAG' #Percentage of text left of the scrollbar position _FRACTION_LEFT_TEXT=0.30 def __init__(self): self.queue = q.Queue() self.model = ConcordanceSearchModel(self.queue) self.top = Tk() self._init_top(self.top) self._init_menubar() self._init_widgets(self.top) self.load_corpus(self.model.DEFAULT_CORPUS) self.after = self.top.after(POLL_INTERVAL, self._poll) def _init_top(self, top): top.geometry('950x680+50+50') top.title('NLTK Concordance Search') top.bind('<Control-q>', self.destroy) top.protocol('WM_DELETE_WINDOW', self.destroy) top.minsize(950,680) def _init_widgets(self, parent): self.main_frame = Frame(parent, dict(background=self._BACKGROUND_COLOUR, padx=1, pady=1, border=1)) self._init_corpus_select(self.main_frame) self._init_query_box(self.main_frame) self._init_results_box(self.main_frame) self._init_paging(self.main_frame) self._init_status(self.main_frame) self.main_frame.pack(fill='both', expand=True) def _init_menubar(self): self._result_size = IntVar(self.top) self._cntx_bf_len = IntVar(self.top) self._cntx_af_len = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-q') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton(label='20', variable=self._result_size, underline=0, value=20, command=self.set_result_size) rescntmenu.add_radiobutton(label='50', variable=self._result_size, underline=0, value=50, command=self.set_result_size) rescntmenu.add_radiobutton(label='100', variable=self._result_size, underline=0, value=100, command=self.set_result_size) rescntmenu.invoke(1) editmenu.add_cascade(label='Result Count', underline=0, menu=rescntmenu) cntxmenu = Menu(editmenu, tearoff=0) cntxbfmenu = Menu(cntxmenu, tearoff=0) cntxbfmenu.add_radiobutton(label='60 characters', variable=self._cntx_bf_len, underline=0, value=60, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='80 characters', variable=self._cntx_bf_len, underline=0, value=80, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='100 characters', variable=self._cntx_bf_len, underline=0, value=100, command=self.set_cntx_bf_len) cntxbfmenu.invoke(1) cntxmenu.add_cascade(label='Before', underline=0, menu=cntxbfmenu) cntxafmenu = Menu(cntxmenu, tearoff=0) cntxafmenu.add_radiobutton(label='70 characters', variable=self._cntx_af_len, underline=0, value=70, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='90 characters', variable=self._cntx_af_len, underline=0, value=90, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='110 characters', variable=self._cntx_af_len, underline=0, value=110, command=self.set_cntx_af_len) cntxafmenu.invoke(1) cntxmenu.add_cascade(label='After', underline=0, menu=cntxafmenu) editmenu.add_cascade(label='Context', underline=0, menu=cntxmenu) menubar.add_cascade(label='Edit', underline=0, menu=editmenu) self.top.config(menu=menubar) def set_result_size(self, **kwargs): self.model.result_count = self._result_size.get() def set_cntx_af_len(self, **kwargs): self._char_after = self._cntx_af_len.get() def set_cntx_bf_len(self, **kwargs): self._char_before = self._cntx_bf_len.get() def _init_corpus_select(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.var = StringVar(innerframe) self.var.set(self.model.DEFAULT_CORPUS) Label(innerframe, justify=LEFT, text=' Corpus: ', background=self._BACKGROUND_COLOUR, padx = 2, pady = 1, border = 0).pack(side='left') other_corpora = list(self.model.CORPORA.keys()).remove(self.model.DEFAULT_CORPUS) om = OptionMenu(innerframe, self.var, self.model.DEFAULT_CORPUS, command=self.corpus_selected, *self.model.non_default_corpora()) om['borderwidth'] = 0 om['highlightthickness'] = 1 om.pack(side='left') innerframe.pack(side='top', fill='x', anchor='n') def _init_status(self, parent): self.status = Label(parent, justify=LEFT, relief=SUNKEN, background=self._BACKGROUND_COLOUR, border=0, padx = 1, pady = 0) self.status.pack(side='top', anchor='sw') def _init_query_box(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) another = Frame(innerframe, background=self._BACKGROUND_COLOUR) self.query_box = Entry(another, width=60) self.query_box.pack(side='left', fill='x', pady=25, anchor='center') self.search_button = Button(another, text='Search', command=self.search, borderwidth=1, highlightthickness=1) self.search_button.pack(side='left', fill='x', pady=25, anchor='center') self.query_box.bind('<KeyPress-Return>', self.search_enter_keypress_handler) another.pack() innerframe.pack(side='top', fill='x', anchor='n') def search_enter_keypress_handler(self, *event): self.search() def _init_results_box(self, parent): innerframe = Frame(parent) i1 = Frame(innerframe) i2 = Frame(innerframe) vscrollbar = Scrollbar(i1, borderwidth=1) hscrollbar = Scrollbar(i2, borderwidth=1, orient='horiz') self.results_box = Text(i1, font=Font(family='courier', size='16'), state='disabled', borderwidth=1, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap='none', width='40', height = '20', exportselection=1) self.results_box.pack(side='left', fill='both', expand=True) self.results_box.tag_config(self._HIGHLIGHT_WORD_TAG, foreground=self._HIGHLIGHT_WORD_COLOUR) self.results_box.tag_config(self._HIGHLIGHT_LABEL_TAG, foreground=self._HIGHLIGHT_LABEL_COLOUR) vscrollbar.pack(side='left', fill='y', anchor='e') vscrollbar.config(command=self.results_box.yview) hscrollbar.pack(side='left', fill='x', expand=True, anchor='w') hscrollbar.config(command=self.results_box.xview) #there is no other way of avoiding the overlap of scrollbars while using pack layout manager!!! Label(i2, text=' ', background=self._BACKGROUND_COLOUR).pack(side='left', anchor='e') i1.pack(side='top', fill='both', expand=True, anchor='n') i2.pack(side='bottom', fill='x', anchor='s') innerframe.pack(side='top', fill='both', expand=True) def _init_paging(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.prev = prev = Button(innerframe, text='Previous', command=self.previous, width='10', borderwidth=1, highlightthickness=1, state='disabled') prev.pack(side='left', anchor='center') self.next = next = Button(innerframe, text='Next', command=self.__next__, width='10', borderwidth=1, highlightthickness=1, state='disabled') next.pack(side='right', anchor='center') innerframe.pack(side='top', fill='y') self.current_page = 0 def previous(self): self.clear_results_box() self.freeze_editable() self.model.prev(self.current_page - 1) def __next__(self): self.clear_results_box() self.freeze_editable() self.model.next(self.current_page + 1) def about(self, *e): ABOUT = ("NLTK Concordance Search Demo\n") TITLE = 'About: NLTK Concordance Search Demo' try: from six.moves.tkinter_messagebox import Message Message(message=ABOUT, title=TITLE, parent=self.main_frame).show() except: ShowText(self.top, TITLE, ABOUT) def _bind_event_handlers(self): self.top.bind(CORPUS_LOADED_EVENT, self.handle_corpus_loaded) self.top.bind(SEARCH_TERMINATED_EVENT, self.handle_search_terminated) self.top.bind(SEARCH_ERROR_EVENT, self.handle_search_error) self.top.bind(ERROR_LOADING_CORPUS_EVENT, self.handle_error_loading_corpus) def _poll(self): try: event = self.queue.get(block=False) except q.Empty: pass else: if event == CORPUS_LOADED_EVENT: self.handle_corpus_loaded(event) elif event == SEARCH_TERMINATED_EVENT: self.handle_search_terminated(event) elif event == SEARCH_ERROR_EVENT: self.handle_search_error(event) elif event == ERROR_LOADING_CORPUS_EVENT: self.handle_error_loading_corpus(event) self.after = self.top.after(POLL_INTERVAL, self._poll) def handle_error_loading_corpus(self, event): self.status['text'] = 'Error in loading ' + self.var.get() self.unfreeze_editable() self.clear_all() self.freeze_editable() def handle_corpus_loaded(self, event): self.status['text'] = self.var.get() + ' is loaded' self.unfreeze_editable() self.clear_all() self.query_box.focus_set() def handle_search_terminated(self, event): #todo: refactor the model such that it is less state sensitive results = self.model.get_results() self.write_results(results) self.status['text'] = '' if len(results) == 0: self.status['text'] = 'No results found for ' + self.model.query else: self.current_page = self.model.last_requested_page self.unfreeze_editable() self.results_box.xview_moveto(self._FRACTION_LEFT_TEXT) def handle_search_error(self, event): self.status['text'] = 'Error in query ' + self.model.query self.unfreeze_editable() def corpus_selected(self, *args): new_selection = self.var.get() self.load_corpus(new_selection) def load_corpus(self, selection): if self.model.selected_corpus != selection: self.status['text'] = 'Loading ' + selection + '...' self.freeze_editable() self.model.load_corpus(selection) def search(self): self.current_page = 0 self.clear_results_box() self.model.reset_results() query = self.query_box.get() if (len(query.strip()) == 0): return self.status['text'] = 'Searching for ' + query self.freeze_editable() self.model.search(query, self.current_page + 1, ) def write_results(self, results): self.results_box['state'] = 'normal' row = 1 for each in results: sent, pos1, pos2 = each[0].strip(), each[1], each[2] if len(sent) != 0: if (pos1 < self._char_before): sent, pos1, pos2 = self.pad(sent, pos1, pos2) sentence = sent[pos1-self._char_before:pos1+self._char_after] if not row == len(results): sentence += '\n' self.results_box.insert(str(row) + '.0', sentence) word_markers, label_markers = self.words_and_labels(sent, pos1, pos2) for marker in word_markers: self.results_box.tag_add(self._HIGHLIGHT_WORD_TAG, str(row) + '.' + str(marker[0]), str(row) + '.' + str(marker[1])) for marker in label_markers: self.results_box.tag_add(self._HIGHLIGHT_LABEL_TAG, str(row) + '.' + str(marker[0]), str(row) + '.' + str(marker[1])) row += 1 self.results_box['state'] = 'disabled' def words_and_labels(self, sentence, pos1, pos2): search_exp = sentence[pos1:pos2] words, labels = [], [] labeled_words = search_exp.split(' ') index = 0 for each in labeled_words: if each == '': index += 1 else: word, label = each.split('/') words.append((self._char_before + index, self._char_before + index + len(word))) index += len(word) + 1 labels.append((self._char_before + index, self._char_before + index + len(label))) index += len(label) index += 1 return words, labels def pad(self, sent, hstart, hend): if hstart >= self._char_before: return sent, hstart, hend d = self._char_before - hstart sent = ''.join([' '] * d) + sent return sent, hstart + d, hend + d def destroy(self, *e): if self.top is None: return self.top.after_cancel(self.after) self.top.destroy() self.top = None def clear_all(self): self.query_box.delete(0, END) self.model.reset_query() self.clear_results_box() def clear_results_box(self): self.results_box['state'] = 'normal' self.results_box.delete("1.0", END) self.results_box['state'] = 'disabled' def freeze_editable(self): self.query_box['state'] = 'disabled' self.search_button['state'] = 'disabled' self.prev['state'] = 'disabled' self.next['state'] = 'disabled' def unfreeze_editable(self): self.query_box['state'] = 'normal' self.search_button['state'] = 'normal' self.set_paging_button_states() def set_paging_button_states(self): if self.current_page == 0 or self.current_page == 1: self.prev['state'] = 'disabled' else: self.prev['state'] = 'normal' if self.model.has_more_pages(self.current_page): self.next['state'] = 'normal' else: self.next['state'] = 'disabled' def fire_event(self, event): #Firing an event so that rendering of widgets happen in the mainloop thread self.top.event_generate(event, when='tail') def mainloop(self, *args, **kwargs): if in_idle(): return self.top.mainloop(*args, **kwargs)
class LintGui(object): """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 = six.moves.queue.Queue() self.msgs = [] self.visible_msgs = [] self.filenames = [] self.rating = StringVar() self.tabs = {} self.report_stream = BasicStream(self) #gui objects self.lb_messages = 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""" window = PanedWindow(self.root, orient="vertical") window.pack(side=TOP, fill=BOTH, expand=True) top_pane = Frame(window) window.add(top_pane) mid_pane = Frame(window) window.add(mid_pane) bottom_pane = Frame(window) window.add(bottom_pane) #setting up frames top_frame = Frame(top_pane) mid_frame = Frame(top_pane) history_frame = Frame(top_pane) radio_frame = Frame(mid_pane) rating_frame = Frame(mid_pane) res_frame = Frame(mid_pane) check_frame = Frame(bottom_pane) msg_frame = Frame(bottom_pane) btn_frame = Frame(bottom_pane) 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=X) rating_frame.pack(side=TOP, fill=X) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=X) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) # Binding F5 application-wide to run lint self.root.bind('<F5>', self.run_lint) #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.lb_messages = Listbox(msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white") self.lb_messages.bind("<Double-Button-1>", self.show_sourcefile) self.lb_messages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lb_messages.yview) bottomscrollbar.config(command=self.lb_messages.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) #labelbl_ratingls lbl_rating_label = Label(rating_frame, text='Rating:') lbl_rating_label.pack(side=LEFT) lbl_rating = Label(rating_frame, textvariable=self.rating) lbl_rating.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.txt_module = Entry(top_frame, background='white') self.txt_module.bind('<Return>', self.run_lint) self.txt_module.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) raw_met = 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) msg_cat = 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) source_file = Radiobutton(radio_frame, text="Source File", variable=self.box, value="Source File", command=self.refresh_results_window) report.select() report.grid(column=0, row=0, sticky=W) raw_met.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=W) stat.grid(column=0, row=1, sticky=W) msg_cat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, sticky=W) source_file.grid(column=3, row=1, 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.txt_module.focus_set() def select_recent_file(self, event): # pylint: disable=unused-argument """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.txt_module.delete(0, END) self.txt_module.insert(0, item) def refresh_msg_window(self): """refresh the message window with current output""" #clear the window self.lb_messages.delete(0, END) self.visible_msgs = [] for msg in self.msgs: if self.msg_type_dict.get(msg.C)(): self.visible_msgs.append(msg) msg_str = convert_to_string(msg) self.lb_messages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lb_messages.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 KeyError: pass 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.C)(): self.visible_msgs.append(msg) msg_str = convert_to_string(msg) self.lb_messages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lb_messages.itemconfigure(END, fg=fg_color) except six.moves.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): # pylint: disable=no-self-use """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.txt_module.delete(0, END) self.txt_module.insert(0, filename) def update_filenames(self): """update the list of recent filenames""" filename = self.txt_module.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 hist not 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.txt_module.get() if not module: module = os.getcwd() #cleaning up msgs and windows self.msgs = [] self.visible_msgs = [] self.lb_messages.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='') def show_sourcefile(self, event=None): # pylint: disable=unused-argument selected = self.lb_messages.curselection() if not selected: return msg = self.visible_msgs[int(selected[0])] scroll = msg.line - 3 if scroll < 0: scroll = 0 self.tabs["Source File"] = open(msg.path, "r").readlines() self.box.set("Source File") self.refresh_results_window() self.results.yview(scroll) self.results.select_set(msg.line - 1)
class ConcordanceSearchView(object): _BACKGROUND_COLOUR = "#FFF" # white # Colour of highlighted results _HIGHLIGHT_WORD_COLOUR = "#F00" # red _HIGHLIGHT_WORD_TAG = "HL_WRD_TAG" _HIGHLIGHT_LABEL_COLOUR = "#C0C0C0" # dark grey _HIGHLIGHT_LABEL_TAG = "HL_LBL_TAG" # Percentage of text left of the scrollbar position _FRACTION_LEFT_TEXT = 0.30 def __init__(self): self.queue = q.Queue() self.model = ConcordanceSearchModel(self.queue) self.top = Tk() self._init_top(self.top) self._init_menubar() self._init_widgets(self.top) self.load_corpus(self.model.DEFAULT_CORPUS) self.after = self.top.after(POLL_INTERVAL, self._poll) def _init_top(self, top): top.geometry("950x680+50+50") top.title("NLTK Concordance Search") top.bind("<Control-q>", self.destroy) top.protocol("WM_DELETE_WINDOW", self.destroy) top.minsize(950, 680) def _init_widgets(self, parent): self.main_frame = Frame( parent, dict(background=self._BACKGROUND_COLOUR, padx=1, pady=1, border=1)) self._init_corpus_select(self.main_frame) self._init_query_box(self.main_frame) self._init_results_box(self.main_frame) self._init_paging(self.main_frame) self._init_status(self.main_frame) self.main_frame.pack(fill="both", expand=True) def _init_menubar(self): self._result_size = IntVar(self.top) self._cntx_bf_len = IntVar(self.top) self._cntx_af_len = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label="Exit", underline=1, command=self.destroy, accelerator="Ctrl-q") menubar.add_cascade(label="File", underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton( label="20", variable=self._result_size, underline=0, value=20, command=self.set_result_size, ) rescntmenu.add_radiobutton( label="50", variable=self._result_size, underline=0, value=50, command=self.set_result_size, ) rescntmenu.add_radiobutton( label="100", variable=self._result_size, underline=0, value=100, command=self.set_result_size, ) rescntmenu.invoke(1) editmenu.add_cascade(label="Result Count", underline=0, menu=rescntmenu) cntxmenu = Menu(editmenu, tearoff=0) cntxbfmenu = Menu(cntxmenu, tearoff=0) cntxbfmenu.add_radiobutton( label="60 characters", variable=self._cntx_bf_len, underline=0, value=60, command=self.set_cntx_bf_len, ) cntxbfmenu.add_radiobutton( label="80 characters", variable=self._cntx_bf_len, underline=0, value=80, command=self.set_cntx_bf_len, ) cntxbfmenu.add_radiobutton( label="100 characters", variable=self._cntx_bf_len, underline=0, value=100, command=self.set_cntx_bf_len, ) cntxbfmenu.invoke(1) cntxmenu.add_cascade(label="Before", underline=0, menu=cntxbfmenu) cntxafmenu = Menu(cntxmenu, tearoff=0) cntxafmenu.add_radiobutton( label="70 characters", variable=self._cntx_af_len, underline=0, value=70, command=self.set_cntx_af_len, ) cntxafmenu.add_radiobutton( label="90 characters", variable=self._cntx_af_len, underline=0, value=90, command=self.set_cntx_af_len, ) cntxafmenu.add_radiobutton( label="110 characters", variable=self._cntx_af_len, underline=0, value=110, command=self.set_cntx_af_len, ) cntxafmenu.invoke(1) cntxmenu.add_cascade(label="After", underline=0, menu=cntxafmenu) editmenu.add_cascade(label="Context", underline=0, menu=cntxmenu) menubar.add_cascade(label="Edit", underline=0, menu=editmenu) self.top.config(menu=menubar) def set_result_size(self, **kwargs): self.model.result_count = self._result_size.get() def set_cntx_af_len(self, **kwargs): self._char_after = self._cntx_af_len.get() def set_cntx_bf_len(self, **kwargs): self._char_before = self._cntx_bf_len.get() def _init_corpus_select(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.var = StringVar(innerframe) self.var.set(self.model.DEFAULT_CORPUS) Label( innerframe, justify=LEFT, text=" Corpus: ", background=self._BACKGROUND_COLOUR, padx=2, pady=1, border=0, ).pack(side="left") other_corpora = list(self.model.CORPORA.keys()).remove( self.model.DEFAULT_CORPUS) om = OptionMenu(innerframe, self.var, self.model.DEFAULT_CORPUS, command=self.corpus_selected, *self.model.non_default_corpora()) om["borderwidth"] = 0 om["highlightthickness"] = 1 om.pack(side="left") innerframe.pack(side="top", fill="x", anchor="n") def _init_status(self, parent): self.status = Label( parent, justify=LEFT, relief=SUNKEN, background=self._BACKGROUND_COLOUR, border=0, padx=1, pady=0, ) self.status.pack(side="top", anchor="sw") def _init_query_box(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) another = Frame(innerframe, background=self._BACKGROUND_COLOUR) self.query_box = Entry(another, width=60) self.query_box.pack(side="left", fill="x", pady=25, anchor="center") self.search_button = Button( another, text="Search", command=self.search, borderwidth=1, highlightthickness=1, ) self.search_button.pack(side="left", fill="x", pady=25, anchor="center") self.query_box.bind("<KeyPress-Return>", self.search_enter_keypress_handler) another.pack() innerframe.pack(side="top", fill="x", anchor="n") def search_enter_keypress_handler(self, *event): self.search() def _init_results_box(self, parent): innerframe = Frame(parent) i1 = Frame(innerframe) i2 = Frame(innerframe) vscrollbar = Scrollbar(i1, borderwidth=1) hscrollbar = Scrollbar(i2, borderwidth=1, orient="horiz") self.results_box = Text( i1, font=Font(family="courier", size="16"), state="disabled", borderwidth=1, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap="none", width="40", height="20", exportselection=1, ) self.results_box.pack(side="left", fill="both", expand=True) self.results_box.tag_config(self._HIGHLIGHT_WORD_TAG, foreground=self._HIGHLIGHT_WORD_COLOUR) self.results_box.tag_config(self._HIGHLIGHT_LABEL_TAG, foreground=self._HIGHLIGHT_LABEL_COLOUR) vscrollbar.pack(side="left", fill="y", anchor="e") vscrollbar.config(command=self.results_box.yview) hscrollbar.pack(side="left", fill="x", expand=True, anchor="w") hscrollbar.config(command=self.results_box.xview) # there is no other way of avoiding the overlap of scrollbars while using pack layout manager!!! Label(i2, text=" ", background=self._BACKGROUND_COLOUR).pack(side="left", anchor="e") i1.pack(side="top", fill="both", expand=True, anchor="n") i2.pack(side="bottom", fill="x", anchor="s") innerframe.pack(side="top", fill="both", expand=True) def _init_paging(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.prev = prev = Button( innerframe, text="Previous", command=self.previous, width="10", borderwidth=1, highlightthickness=1, state="disabled", ) prev.pack(side="left", anchor="center") self.next = next = Button( innerframe, text="Next", command=self.__next__, width="10", borderwidth=1, highlightthickness=1, state="disabled", ) next.pack(side="right", anchor="center") innerframe.pack(side="top", fill="y") self.current_page = 0 def previous(self): self.clear_results_box() self.freeze_editable() self.model.prev(self.current_page - 1) def __next__(self): self.clear_results_box() self.freeze_editable() self.model.next(self.current_page + 1) def about(self, *e): ABOUT = "NLTK Concordance Search Demo\n" TITLE = "About: NLTK Concordance Search Demo" try: from six.moves.tkinter_messagebox import Message Message(message=ABOUT, title=TITLE, parent=self.main_frame).show() except: ShowText(self.top, TITLE, ABOUT) def _bind_event_handlers(self): self.top.bind(CORPUS_LOADED_EVENT, self.handle_corpus_loaded) self.top.bind(SEARCH_TERMINATED_EVENT, self.handle_search_terminated) self.top.bind(SEARCH_ERROR_EVENT, self.handle_search_error) self.top.bind(ERROR_LOADING_CORPUS_EVENT, self.handle_error_loading_corpus) def _poll(self): try: event = self.queue.get(block=False) except q.Empty: pass else: if event == CORPUS_LOADED_EVENT: self.handle_corpus_loaded(event) elif event == SEARCH_TERMINATED_EVENT: self.handle_search_terminated(event) elif event == SEARCH_ERROR_EVENT: self.handle_search_error(event) elif event == ERROR_LOADING_CORPUS_EVENT: self.handle_error_loading_corpus(event) self.after = self.top.after(POLL_INTERVAL, self._poll) def handle_error_loading_corpus(self, event): self.status["text"] = "Error in loading " + self.var.get() self.unfreeze_editable() self.clear_all() self.freeze_editable() def handle_corpus_loaded(self, event): self.status["text"] = self.var.get() + " is loaded" self.unfreeze_editable() self.clear_all() self.query_box.focus_set() def handle_search_terminated(self, event): # todo: refactor the model such that it is less state sensitive results = self.model.get_results() self.write_results(results) self.status["text"] = "" if len(results) == 0: self.status["text"] = "No results found for " + self.model.query else: self.current_page = self.model.last_requested_page self.unfreeze_editable() self.results_box.xview_moveto(self._FRACTION_LEFT_TEXT) def handle_search_error(self, event): self.status["text"] = "Error in query " + self.model.query self.unfreeze_editable() def corpus_selected(self, *args): new_selection = self.var.get() self.load_corpus(new_selection) def load_corpus(self, selection): if self.model.selected_corpus != selection: self.status["text"] = "Loading " + selection + "..." self.freeze_editable() self.model.load_corpus(selection) def search(self): self.current_page = 0 self.clear_results_box() self.model.reset_results() query = self.query_box.get() if len(query.strip()) == 0: return self.status["text"] = "Searching for " + query self.freeze_editable() self.model.search(query, self.current_page + 1) def write_results(self, results): self.results_box["state"] = "normal" row = 1 for each in results: sent, pos1, pos2 = each[0].strip(), each[1], each[2] if len(sent) != 0: if pos1 < self._char_before: sent, pos1, pos2 = self.pad(sent, pos1, pos2) sentence = sent[pos1 - self._char_before:pos1 + self._char_after] if not row == len(results): sentence += "\n" self.results_box.insert(str(row) + ".0", sentence) word_markers, label_markers = self.words_and_labels( sent, pos1, pos2) for marker in word_markers: self.results_box.tag_add( self._HIGHLIGHT_WORD_TAG, str(row) + "." + str(marker[0]), str(row) + "." + str(marker[1]), ) for marker in label_markers: self.results_box.tag_add( self._HIGHLIGHT_LABEL_TAG, str(row) + "." + str(marker[0]), str(row) + "." + str(marker[1]), ) row += 1 self.results_box["state"] = "disabled" def words_and_labels(self, sentence, pos1, pos2): search_exp = sentence[pos1:pos2] words, labels = [], [] labeled_words = search_exp.split(" ") index = 0 for each in labeled_words: if each == "": index += 1 else: word, label = each.split("/") words.append((self._char_before + index, self._char_before + index + len(word))) index += len(word) + 1 labels.append((self._char_before + index, self._char_before + index + len(label))) index += len(label) index += 1 return words, labels def pad(self, sent, hstart, hend): if hstart >= self._char_before: return sent, hstart, hend d = self._char_before - hstart sent = "".join([" "] * d) + sent return sent, hstart + d, hend + d def destroy(self, *e): if self.top is None: return self.top.after_cancel(self.after) self.top.destroy() self.top = None def clear_all(self): self.query_box.delete(0, END) self.model.reset_query() self.clear_results_box() def clear_results_box(self): self.results_box["state"] = "normal" self.results_box.delete("1.0", END) self.results_box["state"] = "disabled" def freeze_editable(self): self.query_box["state"] = "disabled" self.search_button["state"] = "disabled" self.prev["state"] = "disabled" self.next["state"] = "disabled" def unfreeze_editable(self): self.query_box["state"] = "normal" self.search_button["state"] = "normal" self.set_paging_button_states() def set_paging_button_states(self): if self.current_page == 0 or self.current_page == 1: self.prev["state"] = "disabled" else: self.prev["state"] = "normal" if self.model.has_more_pages(self.current_page): self.next["state"] = "normal" else: self.next["state"] = "disabled" def fire_event(self, event): # Firing an event so that rendering of widgets happen in the mainloop thread self.top.event_generate(event, when="tail") def mainloop(self, *args, **kwargs): if in_idle(): return self.top.mainloop(*args, **kwargs)
class LintGui(object): """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 = six.moves.queue.Queue() self.msgs = [] self.visible_msgs = [] self.filenames = [] self.rating = StringVar() self.tabs = {} self.report_stream = BasicStream(self) #gui objects self.lb_messages = 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""" window = PanedWindow(self.root, orient="vertical") window.pack(side=TOP, fill=BOTH, expand=True) top_pane = Frame(window) window.add(top_pane) mid_pane = Frame(window) window.add(mid_pane) bottom_pane = Frame(window) window.add(bottom_pane) #setting up frames top_frame = Frame(top_pane) mid_frame = Frame(top_pane) history_frame = Frame(top_pane) radio_frame = Frame(mid_pane) rating_frame = Frame(mid_pane) res_frame = Frame(mid_pane) check_frame = Frame(bottom_pane) msg_frame = Frame(bottom_pane) btn_frame = Frame(bottom_pane) 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=X) rating_frame.pack(side=TOP, fill=X) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=X) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) # Binding F5 application-wide to run lint self.root.bind('<F5>', self.run_lint) #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.lb_messages = Listbox( msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white") self.lb_messages.bind("<Double-Button-1>", self.show_sourcefile) self.lb_messages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lb_messages.yview) bottomscrollbar.config(command=self.lb_messages.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) #labelbl_ratingls lbl_rating_label = Label(rating_frame, text='Rating:') lbl_rating_label.pack(side=LEFT) lbl_rating = Label(rating_frame, textvariable=self.rating) lbl_rating.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.txt_module = Entry(top_frame, background='white') self.txt_module.bind('<Return>', self.run_lint) self.txt_module.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) raw_met = 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) msg_cat = 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) source_file = Radiobutton( radio_frame, text="Source File", variable=self.box, value="Source File", command=self.refresh_results_window) report.select() report.grid(column=0, row=0, sticky=W) raw_met.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=W) stat.grid(column=0, row=1, sticky=W) msg_cat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, sticky=W) source_file.grid(column=3, row=1, 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.txt_module.focus_set() def select_recent_file(self, event): # pylint: disable=unused-argument """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.txt_module.delete(0, END) self.txt_module.insert(0, item) def refresh_msg_window(self): """refresh the message window with current output""" #clear the window self.lb_messages.delete(0, END) self.visible_msgs = [] for msg in self.msgs: if self.msg_type_dict.get(msg.C)(): self.visible_msgs.append(msg) msg_str = convert_to_string(msg) self.lb_messages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lb_messages.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 KeyError: pass 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.C)(): self.visible_msgs.append(msg) msg_str = convert_to_string(msg) self.lb_messages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lb_messages.itemconfigure(END, fg=fg_color) except six.moves.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): # pylint: disable=no-self-use """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.txt_module.delete(0, END) self.txt_module.insert(0, filename) def update_filenames(self): """update the list of recent filenames""" filename = self.txt_module.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.txt_module.get() if not module: module = os.getcwd() #cleaning up msgs and windows self.msgs = [] self.visible_msgs = [] self.lb_messages.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='') def show_sourcefile(self, event=None): # pylint: disable=unused-argument selected = self.lb_messages.curselection() if not selected: return msg = self.visible_msgs[int(selected[0])] scroll = msg.line - 3 if scroll < 0: scroll = 0 self.tabs["Source File"] = open(msg.path, "r").readlines() self.box.set("Source File") self.refresh_results_window() self.results.yview(scroll) self.results.select_set(msg.line - 1)
def __init__(self, parent, root): self.parent = parent self.root = root self.selectedStatus = False # Widget Initialization self._listbox = Listbox( parent, font="{Segoe UI} 10", height=0, selectmode="extended", state="normal", cursor="hand2", exportselection=False, ) self._listbox_scrollbar = AutoScrollbar(self._listbox) self._lbl_help = Label( parent, font="{Segoe UI Light} 12 bold", text="Hold [Ctrl] to select multiple items", ) self._label_header = Label( parent, font="{Segoe UI} 16 bold", text="Playback items available for removal", ) self._label_actions = Label( parent, font="{Segoe UI} 14 bold", text="Actions", ) self._label_info = Label( parent, font="{Segoe UI} 14 bold", text="Info", ) self._btnRefresh = Button( parent, font="{Segoe UI} 12 bold", text="Refresh", ) self._btnRemoveSelected = Button( parent, font="{Segoe UI} 12 bold", wraplength=175, text="Remove Selected", ) self._btnSelectDeselectAll = Button( parent, font="{Segoe UI} 12 bold", wraplength=175, text="Select / Deselect All", ) self._btnStopCurrentlyPlaying = Button( parent, font="{Segoe UI} 12 bold", # wraplength=80, text="Stop Currently Playing", ) self._btnLogin = Button( parent, font="{Segoe UI} 12 bold", text="Login/Auth", ) self._lbl_ID = Label( parent, font="{Segoe UI Light} 12 bold", text="ID:", ) self._lbl_PausedAt = Label( parent, font="{Segoe UI Light} 12 bold", text="Paused At:", ) self._lbl_Progress = Label( parent, font="{Segoe UI Light} 12 bold", text="Progress:", ) self.lbl_showName = StringVar(value="Show:") self._lbl_Show = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_showName, ) self.lbl_season = StringVar(value="Season:") self._lbl_Season = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_season, ) self.lbl_episode = StringVar(value="Episode:") self._lbl_Episode = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_episode, ) self.lbl_episodeTitle = StringVar(value="Title:") self._lbl_Title = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_episodeTitle, ) self.txt_ID = StringVar() self._txtID = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_ID, width=0, ) self.txt_paused_at = StringVar() self._txtPausedAt = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_paused_at, width=0, ) self.txt_progress = StringVar() self._txtProgress = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_progress, width=0, ) self.txt_showName = StringVar() self._txtShowName = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_showName, width=0, ) self.txt_season = StringVar() self._txtSeason = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_season, width=0, ) self.txt_episode = StringVar() self._txtEpisode = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_episode, width=0, ) self.txt_title = StringVar() self._txtTitle = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_title, width=0, ) self.lbl_loggedin = StringVar(value="") self._lbl_loggedin = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_loggedin, ) self._lbl_version = Label( parent, font="{Segoe UI Light} 10 bold", text="v%s" % app.__version__, foreground="blue", cursor="hand2", ) # widget commands self._listbox.bind('<<ListboxSelect>>', self._listbox_onselect) self._listbox.config(yscrollcommand=self._listbox_scrollbar.set) self._listbox_scrollbar.config(orient='vertical', command=self._listbox.yview) self._btnRefresh.configure(command=self._btn_refresh_command) self._btnRemoveSelected.configure( command=self._btn_remove_selected_command) self._btnSelectDeselectAll.configure( command=self._btn_toggle_selection_command) self._btnStopCurrentlyPlaying.configure( command=self._btn_stop_currently_playing) self._btnLogin.configure(command=self._btn_login_command) self._lbl_version.bind('<Button-1>', self._open_repo) # Geometry Management self._listbox.grid(in_=parent, column=4, row=2, columnspan=1, ipadx=0, ipady=0, padx=5, pady=5, rowspan=10, sticky="nsew") self._listbox.columnconfigure(0, weight=1) self._listbox.rowconfigure(0, weight=1) self._listbox_scrollbar.grid(column=4, rowspan=10, sticky="ns") self._lbl_help.grid(in_=parent, column=4, row=11, ipadx=0, ipady=0, padx=5, pady=5, sticky="nsew") self._label_header.grid(in_=parent, column=4, row=1, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nsew") self._label_actions.grid(in_=parent, column=1, row=9, columnspan=3, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nsew") self._label_info.grid(in_=parent, column=1, row=1, columnspan=3, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nsew") self._btnRefresh.grid(in_=parent, column=1, row=10, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") self._btnRemoveSelected.grid(in_=parent, column=2, row=10, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") self._btnSelectDeselectAll.grid(in_=parent, column=3, row=10, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") self._btnStopCurrentlyPlaying.grid(in_=parent, column=2, row=11, columnspan=2, ipadx=0, ipady=0, padx=5, pady=0, rowspan=1, sticky="ne") self._btnLogin.grid(in_=parent, column=2, row=11, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") # Hide the login button at first self._btnLogin.grid_remove() self._lbl_ID.grid(in_=parent, column=1, row=2, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_PausedAt.grid(in_=parent, column=1, row=3, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Progress.grid(in_=parent, column=1, row=4, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Show.grid(in_=parent, column=1, row=5, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Season.grid(in_=parent, column=1, row=6, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Episode.grid(in_=parent, column=1, row=7, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Title.grid(in_=parent, column=1, row=8, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._txtID.grid(in_=parent, column=2, row=2, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtPausedAt.grid(in_=parent, column=2, row=3, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtProgress.grid(in_=parent, column=2, row=4, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtShowName.grid(in_=parent, column=2, row=5, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtSeason.grid(in_=parent, column=2, row=6, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtEpisode.grid(in_=parent, column=2, row=7, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtTitle.grid(in_=parent, column=2, row=8, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._lbl_loggedin.grid(in_=parent, column=1, row=11, columnspan=2, ipadx=0, ipady=0, padx=5, pady=5, rowspan=1, sticky="sw") self._lbl_version.grid(in_=parent, column=1, row=1, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nw") # Resize Behavior parent.resizable(False, False) parent.grid_rowconfigure(1, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(2, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(3, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(4, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(5, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(6, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(7, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(8, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(9, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(10, weight=0, minsize=60, pad=0) parent.grid_rowconfigure(11, weight=0, minsize=30, pad=5) parent.grid_columnconfigure(1, weight=0, minsize=70, pad=5) parent.grid_columnconfigure(2, weight=0, minsize=175, pad=0) parent.grid_columnconfigure(3, weight=0, minsize=175, pad=0) parent.grid_columnconfigure(4, weight=0, minsize=400, pad=0)
class LoginDialog(object): def __init__(self, host): self.__interna_init() self.__host = host self.__initialized = False if TKTk is not None: self.__create_content() self.__initialized = True def __interna_init(self): self.__rootFrame = None self.__top = None self.__usrEntry = None self.__pwdEntry = None self.__accepted = False self.__host = None self.__usr = None self.__pwd = None def __cancel_action(self): self.__accepted = False self.__rootFrame.destroy() def __login_action(self): self.__accepted = True self.__usr = self.__usrEntry.get() self.__pwd = self.__pwdEntry.get() self.__rootFrame.destroy() def __enter_action(self, event): self.__login_action() def __create_content(self): self.__rootFrame = TKTk() self.__rootFrame.withdraw() self.__top = TKToplevel(self.__rootFrame) self.__top.title("Login") self.__top.protocol("WM_DELETE_WINDOW", self.__rootFrame.destroy) self.__top.bind('<Return>', self.__enter_action) self.__top.update_idletasks() width = self.__top.winfo_width() height = self.__top.winfo_height() x = (self.__top.winfo_screenwidth() // 2) - (width // 2) y = (self.__top.winfo_screenheight() // 2) - (height // 2) self.__top.geometry("+%d+%d" % (x, y)) row = 0 expLabel = TKLabel(self.__top, text='Login to host:') expLabel.grid(row=row, column=0, columnspan=4, padx=5, pady=2) row = row + 1 urlLabel = TKLabel(self.__top, text=self.__host) urlLabel.grid(row=row, column=0, columnspan=4, padx=5, pady=2) row = row + 1 usrLabel = TKLabel(self.__top, text='User') usrLabel.grid(row=row, column=0, columnspan=2, padx=20, pady=5) self.__usrEntry = TKEntry(self.__top, width=20) self.__usrEntry.grid(row=row, column=2, columnspan=2, padx=5, pady=5) row = row + 1 pwdLabel = TKLabel(self.__top, text='Password') pwdLabel.grid(row=row, column=0, columnspan=2, padx=20, pady=5) self.__pwdEntry = TKEntry(self.__top, width=20, show="*") self.__pwdEntry.grid(row=row, column=2, columnspan=2, padx=5, pady=5) row = row + 1 cancelButton = TKButton(self.__top, text='Cancel', command=self.__cancel_action) cancelButton.grid(row=row, column=1, padx=5, pady=5) loginButton = TKButton(self.__top, text='Login', command=self.__login_action) loginButton.grid(row=row, column=2, padx=5, pady=5) def show_login(self): if self.__initialized: self.__usrEntry.focus_set() self.__rootFrame.mainloop() else: print("tkinter python module is not available.\n\ Please, install tkinter module or use command line login utility.") def is_accepted(self): return self.__accepted def get_user(self): return self.__usr def get_password(self): return self.__pwd
class CFGEditor(object): """ A dialog window for creating and editing context free grammars. ``CFGEditor`` imposes the following restrictions: - All nonterminals must be strings consisting of word characters. - All terminals must be strings consisting of word characters and space characters. """ # Regular expressions used by _analyze_line. Precompile them, so # we can process the text faster. ARROW = SymbolWidget.SYMBOLS['rightarrow'] _LHS_RE = re.compile(r"(^\s*\w+\s*)(->|(" + ARROW + "))") _ARROW_RE = re.compile("\s*(->|(" + ARROW + "))\s*") _PRODUCTION_RE = re.compile( r"(^\s*\w+\s*)" + "(->|(" # LHS + ARROW + "))\s*" + r"((\w+|'[\w ]*'|\"[\w ]*\"|\|)\s*)*$" # arrow ) # RHS _TOKEN_RE = re.compile("\\w+|->|'[\\w ]+'|\"[\\w ]+\"|(" + ARROW + ")") _BOLD = ('helvetica', -12, 'bold') def __init__(self, parent, cfg=None, set_cfg_callback=None): self._parent = parent if cfg is not None: self._cfg = cfg else: self._cfg = CFG(Nonterminal('S'), []) self._set_cfg_callback = set_cfg_callback self._highlight_matching_nonterminals = 1 # Create the top-level window. self._top = Toplevel(parent) self._init_bindings() self._init_startframe() self._startframe.pack(side='top', fill='x', expand=0) self._init_prodframe() self._prodframe.pack(side='top', fill='both', expand=1) self._init_buttons() self._buttonframe.pack(side='bottom', fill='x', expand=0) self._textwidget.focus() def _init_startframe(self): frame = self._startframe = Frame(self._top) self._start = Entry(frame) self._start.pack(side='right') Label(frame, text='Start Symbol:').pack(side='right') Label(frame, text='Productions:').pack(side='left') self._start.insert(0, self._cfg.start().symbol()) def _init_buttons(self): frame = self._buttonframe = Frame(self._top) Button(frame, text='Ok', command=self._ok, underline=0, takefocus=0).pack( side='left' ) Button(frame, text='Apply', command=self._apply, underline=0, takefocus=0).pack( side='left' ) Button(frame, text='Reset', command=self._reset, underline=0, takefocus=0).pack( side='left' ) Button( frame, text='Cancel', command=self._cancel, underline=0, takefocus=0 ).pack(side='left') Button(frame, text='Help', command=self._help, underline=0, takefocus=0).pack( side='right' ) def _init_bindings(self): self._top.title('CFG Editor') self._top.bind('<Control-q>', self._cancel) self._top.bind('<Alt-q>', self._cancel) self._top.bind('<Control-d>', self._cancel) # self._top.bind('<Control-x>', self._cancel) self._top.bind('<Alt-x>', self._cancel) self._top.bind('<Escape>', self._cancel) # self._top.bind('<Control-c>', self._cancel) self._top.bind('<Alt-c>', self._cancel) self._top.bind('<Control-o>', self._ok) self._top.bind('<Alt-o>', self._ok) self._top.bind('<Control-a>', self._apply) self._top.bind('<Alt-a>', self._apply) self._top.bind('<Control-r>', self._reset) self._top.bind('<Alt-r>', self._reset) self._top.bind('<Control-h>', self._help) self._top.bind('<Alt-h>', self._help) self._top.bind('<F1>', self._help) def _init_prodframe(self): self._prodframe = Frame(self._top) # Create the basic Text widget & scrollbar. self._textwidget = Text( self._prodframe, background='#e0e0e0', exportselection=1 ) self._textscroll = Scrollbar(self._prodframe, takefocus=0, orient='vertical') self._textwidget.config(yscrollcommand=self._textscroll.set) self._textscroll.config(command=self._textwidget.yview) self._textscroll.pack(side='right', fill='y') self._textwidget.pack(expand=1, fill='both', side='left') # Initialize the colorization tags. Each nonterminal gets its # own tag, so they aren't listed here. self._textwidget.tag_config('terminal', foreground='#006000') self._textwidget.tag_config('arrow', font='symbol') self._textwidget.tag_config('error', background='red') # Keep track of what line they're on. We use that to remember # to re-analyze a line whenever they leave it. self._linenum = 0 # Expand "->" to an arrow. self._top.bind('>', self._replace_arrows) # Re-colorize lines when appropriate. self._top.bind('<<Paste>>', self._analyze) self._top.bind('<KeyPress>', self._check_analyze) self._top.bind('<ButtonPress>', self._check_analyze) # Tab cycles focus. (why doesn't this work??) def cycle(e, textwidget=self._textwidget): textwidget.tk_focusNext().focus() self._textwidget.bind('<Tab>', cycle) prod_tuples = [(p.lhs(), [p.rhs()]) for p in self._cfg.productions()] for i in range(len(prod_tuples) - 1, 0, -1): if prod_tuples[i][0] == prod_tuples[i - 1][0]: if () in prod_tuples[i][1]: continue if () in prod_tuples[i - 1][1]: continue print(prod_tuples[i - 1][1]) print(prod_tuples[i][1]) prod_tuples[i - 1][1].extend(prod_tuples[i][1]) del prod_tuples[i] for lhs, rhss in prod_tuples: print(lhs, rhss) s = '%s ->' % lhs for rhs in rhss: for elt in rhs: if isinstance(elt, Nonterminal): s += ' %s' % elt else: s += ' %r' % elt s += ' |' s = s[:-2] + '\n' self._textwidget.insert('end', s) self._analyze() # # Add the producitons to the text widget, and colorize them. # prod_by_lhs = {} # for prod in self._cfg.productions(): # if len(prod.rhs()) > 0: # prod_by_lhs.setdefault(prod.lhs(),[]).append(prod) # for (lhs, prods) in prod_by_lhs.items(): # self._textwidget.insert('end', '%s ->' % lhs) # self._textwidget.insert('end', self._rhs(prods[0])) # for prod in prods[1:]: # print '\t|'+self._rhs(prod), # self._textwidget.insert('end', '\t|'+self._rhs(prod)) # print # self._textwidget.insert('end', '\n') # for prod in self._cfg.productions(): # if len(prod.rhs()) == 0: # self._textwidget.insert('end', '%s' % prod) # self._analyze() # def _rhs(self, prod): # s = '' # for elt in prod.rhs(): # if isinstance(elt, Nonterminal): s += ' %s' % elt.symbol() # else: s += ' %r' % elt # return s def _clear_tags(self, linenum): """ Remove all tags (except ``arrow`` and ``sel``) from the given line of the text widget used for editing the productions. """ start = '%d.0' % linenum end = '%d.end' % linenum for tag in self._textwidget.tag_names(): if tag not in ('arrow', 'sel'): self._textwidget.tag_remove(tag, start, end) def _check_analyze(self, *e): """ Check if we've moved to a new line. If we have, then remove all colorization from the line we moved to, and re-colorize the line that we moved from. """ linenum = int(self._textwidget.index('insert').split('.')[0]) if linenum != self._linenum: self._clear_tags(linenum) self._analyze_line(self._linenum) self._linenum = linenum def _replace_arrows(self, *e): """ Replace any ``'->'`` text strings with arrows (char \\256, in symbol font). This searches the whole buffer, but is fast enough to be done anytime they press '>'. """ arrow = '1.0' while True: arrow = self._textwidget.search('->', arrow, 'end+1char') if arrow == '': break self._textwidget.delete(arrow, arrow + '+2char') self._textwidget.insert(arrow, self.ARROW, 'arrow') self._textwidget.insert(arrow, '\t') arrow = '1.0' while True: arrow = self._textwidget.search(self.ARROW, arrow + '+1char', 'end+1char') if arrow == '': break self._textwidget.tag_add('arrow', arrow, arrow + '+1char') def _analyze_token(self, match, linenum): """ Given a line number and a regexp match for a token on that line, colorize the token. Note that the regexp match gives us the token's text, start index (on the line), and end index (on the line). """ # What type of token is it? if match.group()[0] in "'\"": tag = 'terminal' elif match.group() in ('->', self.ARROW): tag = 'arrow' else: # If it's a nonterminal, then set up new bindings, so we # can highlight all instances of that nonterminal when we # put the mouse over it. tag = 'nonterminal_' + match.group() if tag not in self._textwidget.tag_names(): self._init_nonterminal_tag(tag) start = '%d.%d' % (linenum, match.start()) end = '%d.%d' % (linenum, match.end()) self._textwidget.tag_add(tag, start, end) def _init_nonterminal_tag(self, tag, foreground='blue'): self._textwidget.tag_config(tag, foreground=foreground, font=CFGEditor._BOLD) if not self._highlight_matching_nonterminals: return def enter(e, textwidget=self._textwidget, tag=tag): textwidget.tag_config(tag, background='#80ff80') def leave(e, textwidget=self._textwidget, tag=tag): textwidget.tag_config(tag, background='') self._textwidget.tag_bind(tag, '<Enter>', enter) self._textwidget.tag_bind(tag, '<Leave>', leave) def _analyze_line(self, linenum): """ Colorize a given line. """ # Get rid of any tags that were previously on the line. self._clear_tags(linenum) # Get the line line's text string. line = self._textwidget.get(repr(linenum) + '.0', repr(linenum) + '.end') # If it's a valid production, then colorize each token. if CFGEditor._PRODUCTION_RE.match(line): # It's valid; Use _TOKEN_RE to tokenize the production, # and call analyze_token on each token. def analyze_token(match, self=self, linenum=linenum): self._analyze_token(match, linenum) return '' CFGEditor._TOKEN_RE.sub(analyze_token, line) elif line.strip() != '': # It's invalid; show the user where the error is. self._mark_error(linenum, line) def _mark_error(self, linenum, line): """ Mark the location of an error in a line. """ arrowmatch = CFGEditor._ARROW_RE.search(line) if not arrowmatch: # If there's no arrow at all, highlight the whole line. start = '%d.0' % linenum end = '%d.end' % linenum elif not CFGEditor._LHS_RE.match(line): # Otherwise, if the LHS is bad, highlight it. start = '%d.0' % linenum end = '%d.%d' % (linenum, arrowmatch.start()) else: # Otherwise, highlight the RHS. start = '%d.%d' % (linenum, arrowmatch.end()) end = '%d.end' % linenum # If we're highlighting 0 chars, highlight the whole line. if self._textwidget.compare(start, '==', end): start = '%d.0' % linenum end = '%d.end' % linenum self._textwidget.tag_add('error', start, end) def _analyze(self, *e): """ Replace ``->`` with arrows, and colorize the entire buffer. """ self._replace_arrows() numlines = int(self._textwidget.index('end').split('.')[0]) for linenum in range(1, numlines + 1): # line numbers start at 1. self._analyze_line(linenum) def _parse_productions(self): """ Parse the current contents of the textwidget buffer, to create a list of productions. """ productions = [] # Get the text, normalize it, and split it into lines. text = self._textwidget.get('1.0', 'end') text = re.sub(self.ARROW, '->', text) text = re.sub('\t', ' ', text) lines = text.split('\n') # Convert each line to a CFG production for line in lines: line = line.strip() if line == '': continue productions += _read_cfg_production(line) # if line.strip() == '': continue # if not CFGEditor._PRODUCTION_RE.match(line): # raise ValueError('Bad production string %r' % line) # # (lhs_str, rhs_str) = line.split('->') # lhs = Nonterminal(lhs_str.strip()) # rhs = [] # def parse_token(match, rhs=rhs): # token = match.group() # if token[0] in "'\"": rhs.append(token[1:-1]) # else: rhs.append(Nonterminal(token)) # return '' # CFGEditor._TOKEN_RE.sub(parse_token, rhs_str) # # productions.append(Production(lhs, *rhs)) return productions def _destroy(self, *e): if self._top is None: return self._top.destroy() self._top = None def _ok(self, *e): self._apply() self._destroy() def _apply(self, *e): productions = self._parse_productions() start = Nonterminal(self._start.get()) cfg = CFG(start, productions) if self._set_cfg_callback is not None: self._set_cfg_callback(cfg) def _reset(self, *e): self._textwidget.delete('1.0', 'end') for production in self._cfg.productions(): self._textwidget.insert('end', '%s\n' % production) self._analyze() if self._set_cfg_callback is not None: self._set_cfg_callback(self._cfg) def _cancel(self, *e): try: self._reset() except: pass self._destroy() def _help(self, *e): # The default font's not very legible; try using 'fixed' instead. try: ShowText( self._parent, 'Help: Chart Parser Demo', (_CFGEditor_HELP).strip(), width=75, font='fixed', ) except: ShowText( self._parent, 'Help: Chart Parser Demo', (_CFGEditor_HELP).strip(), width=75, )
class CFGEditor(object): """ A dialog window for creating and editing context free grammars. ``CFGEditor`` imposes the following restrictions: - All nonterminals must be strings consisting of word characters. - All terminals must be strings consisting of word characters and space characters. """ # Regular expressions used by _analyze_line. Precompile them, so # we can process the text faster. ARROW = SymbolWidget.SYMBOLS['rightarrow'] _LHS_RE = re.compile(r"(^\s*\w+\s*)(->|("+ARROW+"))") _ARROW_RE = re.compile("\s*(->|("+ARROW+"))\s*") _PRODUCTION_RE = re.compile(r"(^\s*\w+\s*)" + # LHS "(->|("+ARROW+"))\s*" + # arrow r"((\w+|'[\w ]*'|\"[\w ]*\"|\|)\s*)*$") # RHS _TOKEN_RE = re.compile("\\w+|->|'[\\w ]+'|\"[\\w ]+\"|("+ARROW+")") _BOLD = ('helvetica', -12, 'bold') def __init__(self, parent, cfg=None, set_cfg_callback=None): self._parent = parent if cfg is not None: self._cfg = cfg else: self._cfg = CFG(Nonterminal('S'), []) self._set_cfg_callback = set_cfg_callback self._highlight_matching_nonterminals = 1 # Create the top-level window. self._top = Toplevel(parent) self._init_bindings() self._init_startframe() self._startframe.pack(side='top', fill='x', expand=0) self._init_prodframe() self._prodframe.pack(side='top', fill='both', expand=1) self._init_buttons() self._buttonframe.pack(side='bottom', fill='x', expand=0) self._textwidget.focus() def _init_startframe(self): frame = self._startframe = Frame(self._top) self._start = Entry(frame) self._start.pack(side='right') Label(frame, text='Start Symbol:').pack(side='right') Label(frame, text='Productions:').pack(side='left') self._start.insert(0, self._cfg.start().symbol()) def _init_buttons(self): frame = self._buttonframe = Frame(self._top) Button(frame, text='Ok', command=self._ok, underline=0, takefocus=0).pack(side='left') Button(frame, text='Apply', command=self._apply, underline=0, takefocus=0).pack(side='left') Button(frame, text='Reset', command=self._reset, underline=0, takefocus=0,).pack(side='left') Button(frame, text='Cancel', command=self._cancel, underline=0, takefocus=0).pack(side='left') Button(frame, text='Help', command=self._help, underline=0, takefocus=0).pack(side='right') def _init_bindings(self): self._top.title('CFG Editor') self._top.bind('<Control-q>', self._cancel) self._top.bind('<Alt-q>', self._cancel) self._top.bind('<Control-d>', self._cancel) #self._top.bind('<Control-x>', self._cancel) self._top.bind('<Alt-x>', self._cancel) self._top.bind('<Escape>', self._cancel) #self._top.bind('<Control-c>', self._cancel) self._top.bind('<Alt-c>', self._cancel) self._top.bind('<Control-o>', self._ok) self._top.bind('<Alt-o>', self._ok) self._top.bind('<Control-a>', self._apply) self._top.bind('<Alt-a>', self._apply) self._top.bind('<Control-r>', self._reset) self._top.bind('<Alt-r>', self._reset) self._top.bind('<Control-h>', self._help) self._top.bind('<Alt-h>', self._help) self._top.bind('<F1>', self._help) def _init_prodframe(self): self._prodframe = Frame(self._top) # Create the basic Text widget & scrollbar. self._textwidget = Text(self._prodframe, background='#e0e0e0', exportselection=1) self._textscroll = Scrollbar(self._prodframe, takefocus=0, orient='vertical') self._textwidget.config(yscrollcommand = self._textscroll.set) self._textscroll.config(command=self._textwidget.yview) self._textscroll.pack(side='right', fill='y') self._textwidget.pack(expand=1, fill='both', side='left') # Initialize the colorization tags. Each nonterminal gets its # own tag, so they aren't listed here. self._textwidget.tag_config('terminal', foreground='#006000') self._textwidget.tag_config('arrow', font='symbol') self._textwidget.tag_config('error', background='red') # Keep track of what line they're on. We use that to remember # to re-analyze a line whenever they leave it. self._linenum = 0 # Expand "->" to an arrow. self._top.bind('>', self._replace_arrows) # Re-colorize lines when appropriate. self._top.bind('<<Paste>>', self._analyze) self._top.bind('<KeyPress>', self._check_analyze) self._top.bind('<ButtonPress>', self._check_analyze) # Tab cycles focus. (why doesn't this work??) def cycle(e, textwidget=self._textwidget): textwidget.tk_focusNext().focus() self._textwidget.bind('<Tab>', cycle) prod_tuples = [(p.lhs(),[p.rhs()]) for p in self._cfg.productions()] for i in range(len(prod_tuples)-1,0,-1): if (prod_tuples[i][0] == prod_tuples[i-1][0]): if () in prod_tuples[i][1]: continue if () in prod_tuples[i-1][1]: continue print(prod_tuples[i-1][1]) print(prod_tuples[i][1]) prod_tuples[i-1][1].extend(prod_tuples[i][1]) del prod_tuples[i] for lhs, rhss in prod_tuples: print(lhs, rhss) s = '%s ->' % lhs for rhs in rhss: for elt in rhs: if isinstance(elt, Nonterminal): s += ' %s' % elt else: s += ' %r' % elt s += ' |' s = s[:-2] + '\n' self._textwidget.insert('end', s) self._analyze() # # Add the producitons to the text widget, and colorize them. # prod_by_lhs = {} # for prod in self._cfg.productions(): # if len(prod.rhs()) > 0: # prod_by_lhs.setdefault(prod.lhs(),[]).append(prod) # for (lhs, prods) in prod_by_lhs.items(): # self._textwidget.insert('end', '%s ->' % lhs) # self._textwidget.insert('end', self._rhs(prods[0])) # for prod in prods[1:]: # print '\t|'+self._rhs(prod), # self._textwidget.insert('end', '\t|'+self._rhs(prod)) # print # self._textwidget.insert('end', '\n') # for prod in self._cfg.productions(): # if len(prod.rhs()) == 0: # self._textwidget.insert('end', '%s' % prod) # self._analyze() # def _rhs(self, prod): # s = '' # for elt in prod.rhs(): # if isinstance(elt, Nonterminal): s += ' %s' % elt.symbol() # else: s += ' %r' % elt # return s def _clear_tags(self, linenum): """ Remove all tags (except ``arrow`` and ``sel``) from the given line of the text widget used for editing the productions. """ start = '%d.0'%linenum end = '%d.end'%linenum for tag in self._textwidget.tag_names(): if tag not in ('arrow', 'sel'): self._textwidget.tag_remove(tag, start, end) def _check_analyze(self, *e): """ Check if we've moved to a new line. If we have, then remove all colorization from the line we moved to, and re-colorize the line that we moved from. """ linenum = int(self._textwidget.index('insert').split('.')[0]) if linenum != self._linenum: self._clear_tags(linenum) self._analyze_line(self._linenum) self._linenum = linenum def _replace_arrows(self, *e): """ Replace any ``'->'`` text strings with arrows (char \\256, in symbol font). This searches the whole buffer, but is fast enough to be done anytime they press '>'. """ arrow = '1.0' while True: arrow = self._textwidget.search('->', arrow, 'end+1char') if arrow == '': break self._textwidget.delete(arrow, arrow+'+2char') self._textwidget.insert(arrow, self.ARROW, 'arrow') self._textwidget.insert(arrow, '\t') arrow = '1.0' while True: arrow = self._textwidget.search(self.ARROW, arrow+'+1char', 'end+1char') if arrow == '': break self._textwidget.tag_add('arrow', arrow, arrow+'+1char') def _analyze_token(self, match, linenum): """ Given a line number and a regexp match for a token on that line, colorize the token. Note that the regexp match gives us the token's text, start index (on the line), and end index (on the line). """ # What type of token is it? if match.group()[0] in "'\"": tag = 'terminal' elif match.group() in ('->', self.ARROW): tag = 'arrow' else: # If it's a nonterminal, then set up new bindings, so we # can highlight all instances of that nonterminal when we # put the mouse over it. tag = 'nonterminal_'+match.group() if tag not in self._textwidget.tag_names(): self._init_nonterminal_tag(tag) start = '%d.%d' % (linenum, match.start()) end = '%d.%d' % (linenum, match.end()) self._textwidget.tag_add(tag, start, end) def _init_nonterminal_tag(self, tag, foreground='blue'): self._textwidget.tag_config(tag, foreground=foreground, font=CFGEditor._BOLD) if not self._highlight_matching_nonterminals: return def enter(e, textwidget=self._textwidget, tag=tag): textwidget.tag_config(tag, background='#80ff80') def leave(e, textwidget=self._textwidget, tag=tag): textwidget.tag_config(tag, background='') self._textwidget.tag_bind(tag, '<Enter>', enter) self._textwidget.tag_bind(tag, '<Leave>', leave) def _analyze_line(self, linenum): """ Colorize a given line. """ # Get rid of any tags that were previously on the line. self._clear_tags(linenum) # Get the line line's text string. line = self._textwidget.get(repr(linenum)+'.0', repr(linenum)+'.end') # If it's a valid production, then colorize each token. if CFGEditor._PRODUCTION_RE.match(line): # It's valid; Use _TOKEN_RE to tokenize the production, # and call analyze_token on each token. def analyze_token(match, self=self, linenum=linenum): self._analyze_token(match, linenum) return '' CFGEditor._TOKEN_RE.sub(analyze_token, line) elif line.strip() != '': # It's invalid; show the user where the error is. self._mark_error(linenum, line) def _mark_error(self, linenum, line): """ Mark the location of an error in a line. """ arrowmatch = CFGEditor._ARROW_RE.search(line) if not arrowmatch: # If there's no arrow at all, highlight the whole line. start = '%d.0' % linenum end = '%d.end' % linenum elif not CFGEditor._LHS_RE.match(line): # Otherwise, if the LHS is bad, highlight it. start = '%d.0' % linenum end = '%d.%d' % (linenum, arrowmatch.start()) else: # Otherwise, highlight the RHS. start = '%d.%d' % (linenum, arrowmatch.end()) end = '%d.end' % linenum # If we're highlighting 0 chars, highlight the whole line. if self._textwidget.compare(start, '==', end): start = '%d.0' % linenum end = '%d.end' % linenum self._textwidget.tag_add('error', start, end) def _analyze(self, *e): """ Replace ``->`` with arrows, and colorize the entire buffer. """ self._replace_arrows() numlines = int(self._textwidget.index('end').split('.')[0]) for linenum in range(1, numlines+1): # line numbers start at 1. self._analyze_line(linenum) def _parse_productions(self): """ Parse the current contents of the textwidget buffer, to create a list of productions. """ productions = [] # Get the text, normalize it, and split it into lines. text = self._textwidget.get('1.0', 'end') text = re.sub(self.ARROW, '->', text) text = re.sub('\t', ' ', text) lines = text.split('\n') # Convert each line to a CFG production for line in lines: line = line.strip() if line=='': continue productions += _read_cfg_production(line) #if line.strip() == '': continue #if not CFGEditor._PRODUCTION_RE.match(line): # raise ValueError('Bad production string %r' % line) # #(lhs_str, rhs_str) = line.split('->') #lhs = Nonterminal(lhs_str.strip()) #rhs = [] #def parse_token(match, rhs=rhs): # token = match.group() # if token[0] in "'\"": rhs.append(token[1:-1]) # else: rhs.append(Nonterminal(token)) # return '' #CFGEditor._TOKEN_RE.sub(parse_token, rhs_str) # #productions.append(Production(lhs, *rhs)) return productions def _destroy(self, *e): if self._top is None: return self._top.destroy() self._top = None def _ok(self, *e): self._apply() self._destroy() def _apply(self, *e): productions = self._parse_productions() start = Nonterminal(self._start.get()) cfg = CFG(start, productions) if self._set_cfg_callback is not None: self._set_cfg_callback(cfg) def _reset(self, *e): self._textwidget.delete('1.0', 'end') for production in self._cfg.productions(): self._textwidget.insert('end', '%s\n' % production) self._analyze() if self._set_cfg_callback is not None: self._set_cfg_callback(self._cfg) def _cancel(self, *e): try: self._reset() except: pass self._destroy() def _help(self, *e): # The default font's not very legible; try using 'fixed' instead. try: ShowText(self._parent, 'Help: Chart Parser Demo', (_CFGEditor_HELP).strip(), width=75, font='fixed') except: ShowText(self._parent, 'Help: Chart Parser Demo', (_CFGEditor_HELP).strip(), width=75)
def __init__(self, *args, **kw): Entry.__init__(self, *args, **kw) self.bind("<Control-Key>", self._on_ctrl_key_generic)
class ConcordanceSearchView(object): _BACKGROUND_COLOUR = '#FFF' #white #Colour of highlighted results _HIGHLIGHT_WORD_COLOUR = '#F00' #red _HIGHLIGHT_WORD_TAG = 'HL_WRD_TAG' _HIGHLIGHT_LABEL_COLOUR = '#C0C0C0' # dark grey _HIGHLIGHT_LABEL_TAG = 'HL_LBL_TAG' #Percentage of text left of the scrollbar position _FRACTION_LEFT_TEXT = 0.30 def __init__(self): self.queue = q.Queue() self.model = ConcordanceSearchModel(self.queue) self.top = Tk() self._init_top(self.top) self._init_menubar() self._init_widgets(self.top) self.load_corpus(self.model.DEFAULT_CORPUS) self.after = self.top.after(POLL_INTERVAL, self._poll) def _init_top(self, top): top.geometry('950x680+50+50') top.title('NLTK Concordance Search') top.bind('<Control-q>', self.destroy) top.protocol('WM_DELETE_WINDOW', self.destroy) top.minsize(950, 680) def _init_widgets(self, parent): self.main_frame = Frame( parent, dict(background=self._BACKGROUND_COLOUR, padx=1, pady=1, border=1)) self._init_corpus_select(self.main_frame) self._init_query_box(self.main_frame) self._init_results_box(self.main_frame) self._init_paging(self.main_frame) self._init_status(self.main_frame) self.main_frame.pack(fill='both', expand=True) def _init_menubar(self): self._result_size = IntVar(self.top) self._cntx_bf_len = IntVar(self.top) self._cntx_af_len = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-q') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton(label='20', variable=self._result_size, underline=0, value=20, command=self.set_result_size) rescntmenu.add_radiobutton(label='50', variable=self._result_size, underline=0, value=50, command=self.set_result_size) rescntmenu.add_radiobutton(label='100', variable=self._result_size, underline=0, value=100, command=self.set_result_size) rescntmenu.invoke(1) editmenu.add_cascade(label='Result Count', underline=0, menu=rescntmenu) cntxmenu = Menu(editmenu, tearoff=0) cntxbfmenu = Menu(cntxmenu, tearoff=0) cntxbfmenu.add_radiobutton(label='60 characters', variable=self._cntx_bf_len, underline=0, value=60, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='80 characters', variable=self._cntx_bf_len, underline=0, value=80, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='100 characters', variable=self._cntx_bf_len, underline=0, value=100, command=self.set_cntx_bf_len) cntxbfmenu.invoke(1) cntxmenu.add_cascade(label='Before', underline=0, menu=cntxbfmenu) cntxafmenu = Menu(cntxmenu, tearoff=0) cntxafmenu.add_radiobutton(label='70 characters', variable=self._cntx_af_len, underline=0, value=70, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='90 characters', variable=self._cntx_af_len, underline=0, value=90, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='110 characters', variable=self._cntx_af_len, underline=0, value=110, command=self.set_cntx_af_len) cntxafmenu.invoke(1) cntxmenu.add_cascade(label='After', underline=0, menu=cntxafmenu) editmenu.add_cascade(label='Context', underline=0, menu=cntxmenu) menubar.add_cascade(label='Edit', underline=0, menu=editmenu) self.top.config(menu=menubar) def set_result_size(self, **kwargs): self.model.result_count = self._result_size.get() def set_cntx_af_len(self, **kwargs): self._char_after = self._cntx_af_len.get() def set_cntx_bf_len(self, **kwargs): self._char_before = self._cntx_bf_len.get() def _init_corpus_select(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.var = StringVar(innerframe) self.var.set(self.model.DEFAULT_CORPUS) Label(innerframe, justify=LEFT, text=' Corpus: ', background=self._BACKGROUND_COLOUR, padx=2, pady=1, border=0).pack(side='left') other_corpora = list(self.model.CORPORA.keys()).remove( self.model.DEFAULT_CORPUS) om = OptionMenu(innerframe, self.var, self.model.DEFAULT_CORPUS, command=self.corpus_selected, *self.model.non_default_corpora()) om['borderwidth'] = 0 om['highlightthickness'] = 1 om.pack(side='left') innerframe.pack(side='top', fill='x', anchor='n') def _init_status(self, parent): self.status = Label(parent, justify=LEFT, relief=SUNKEN, background=self._BACKGROUND_COLOUR, border=0, padx=1, pady=0) self.status.pack(side='top', anchor='sw') def _init_query_box(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) another = Frame(innerframe, background=self._BACKGROUND_COLOUR) self.query_box = Entry(another, width=60) self.query_box.pack(side='left', fill='x', pady=25, anchor='center') self.search_button = Button(another, text='Search', command=self.search, borderwidth=1, highlightthickness=1) self.search_button.pack(side='left', fill='x', pady=25, anchor='center') self.query_box.bind('<KeyPress-Return>', self.search_enter_keypress_handler) another.pack() innerframe.pack(side='top', fill='x', anchor='n') def search_enter_keypress_handler(self, *event): self.search() def _init_results_box(self, parent): innerframe = Frame(parent) i1 = Frame(innerframe) i2 = Frame(innerframe) vscrollbar = Scrollbar(i1, borderwidth=1) hscrollbar = Scrollbar(i2, borderwidth=1, orient='horiz') self.results_box = Text(i1, font=Font(family='courier', size='16'), state='disabled', borderwidth=1, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap='none', width='40', height='20', exportselection=1) self.results_box.pack(side='left', fill='both', expand=True) self.results_box.tag_config(self._HIGHLIGHT_WORD_TAG, foreground=self._HIGHLIGHT_WORD_COLOUR) self.results_box.tag_config(self._HIGHLIGHT_LABEL_TAG, foreground=self._HIGHLIGHT_LABEL_COLOUR) vscrollbar.pack(side='left', fill='y', anchor='e') vscrollbar.config(command=self.results_box.yview) hscrollbar.pack(side='left', fill='x', expand=True, anchor='w') hscrollbar.config(command=self.results_box.xview) #there is no other way of avoiding the overlap of scrollbars while using pack layout manager!!! Label(i2, text=' ', background=self._BACKGROUND_COLOUR).pack(side='left', anchor='e') i1.pack(side='top', fill='both', expand=True, anchor='n') i2.pack(side='bottom', fill='x', anchor='s') innerframe.pack(side='top', fill='both', expand=True) def _init_paging(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.prev = prev = Button(innerframe, text='Previous', command=self.previous, width='10', borderwidth=1, highlightthickness=1, state='disabled') prev.pack(side='left', anchor='center') self.next = next = Button(innerframe, text='Next', command=self.__next__, width='10', borderwidth=1, highlightthickness=1, state='disabled') next.pack(side='right', anchor='center') innerframe.pack(side='top', fill='y') self.current_page = 0 def previous(self): self.clear_results_box() self.freeze_editable() self.model.prev(self.current_page - 1) def __next__(self): self.clear_results_box() self.freeze_editable() self.model.next(self.current_page + 1) def about(self, *e): ABOUT = ("NLTK Concordance Search Demo\n") TITLE = 'About: NLTK Concordance Search Demo' try: from six.moves.tkinter_messagebox import Message Message(message=ABOUT, title=TITLE, parent=self.main_frame).show() except: ShowText(self.top, TITLE, ABOUT) def _bind_event_handlers(self): self.top.bind(CORPUS_LOADED_EVENT, self.handle_corpus_loaded) self.top.bind(SEARCH_TERMINATED_EVENT, self.handle_search_terminated) self.top.bind(SEARCH_ERROR_EVENT, self.handle_search_error) self.top.bind(ERROR_LOADING_CORPUS_EVENT, self.handle_error_loading_corpus) def _poll(self): try: event = self.queue.get(block=False) except q.Empty: pass else: if event == CORPUS_LOADED_EVENT: self.handle_corpus_loaded(event) elif event == SEARCH_TERMINATED_EVENT: self.handle_search_terminated(event) elif event == SEARCH_ERROR_EVENT: self.handle_search_error(event) elif event == ERROR_LOADING_CORPUS_EVENT: self.handle_error_loading_corpus(event) self.after = self.top.after(POLL_INTERVAL, self._poll) def handle_error_loading_corpus(self, event): self.status['text'] = 'Error in loading ' + self.var.get() self.unfreeze_editable() self.clear_all() self.freeze_editable() def handle_corpus_loaded(self, event): self.status['text'] = self.var.get() + ' is loaded' self.unfreeze_editable() self.clear_all() self.query_box.focus_set() def handle_search_terminated(self, event): #todo: refactor the model such that it is less state sensitive results = self.model.get_results() self.write_results(results) self.status['text'] = '' if len(results) == 0: self.status['text'] = 'No results found for ' + self.model.query else: self.current_page = self.model.last_requested_page self.unfreeze_editable() self.results_box.xview_moveto(self._FRACTION_LEFT_TEXT) def handle_search_error(self, event): self.status['text'] = 'Error in query ' + self.model.query self.unfreeze_editable() def corpus_selected(self, *args): new_selection = self.var.get() self.load_corpus(new_selection) def load_corpus(self, selection): if self.model.selected_corpus != selection: self.status['text'] = 'Loading ' + selection + '...' self.freeze_editable() self.model.load_corpus(selection) def search(self): self.current_page = 0 self.clear_results_box() self.model.reset_results() query = self.query_box.get() if (len(query.strip()) == 0): return self.status['text'] = 'Searching for ' + query self.freeze_editable() self.model.search( query, self.current_page + 1, ) def write_results(self, results): self.results_box['state'] = 'normal' row = 1 for each in results: sent, pos1, pos2 = each[0].strip(), each[1], each[2] if len(sent) != 0: if (pos1 < self._char_before): sent, pos1, pos2 = self.pad(sent, pos1, pos2) sentence = sent[pos1 - self._char_before:pos1 + self._char_after] if not row == len(results): sentence += '\n' self.results_box.insert(str(row) + '.0', sentence) word_markers, label_markers = self.words_and_labels( sent, pos1, pos2) for marker in word_markers: self.results_box.tag_add(self._HIGHLIGHT_WORD_TAG, str(row) + '.' + str(marker[0]), str(row) + '.' + str(marker[1])) for marker in label_markers: self.results_box.tag_add(self._HIGHLIGHT_LABEL_TAG, str(row) + '.' + str(marker[0]), str(row) + '.' + str(marker[1])) row += 1 self.results_box['state'] = 'disabled' def words_and_labels(self, sentence, pos1, pos2): search_exp = sentence[pos1:pos2] words, labels = [], [] labeled_words = search_exp.split(' ') index = 0 for each in labeled_words: if each == '': index += 1 else: word, label = each.split('/') words.append((self._char_before + index, self._char_before + index + len(word))) index += len(word) + 1 labels.append((self._char_before + index, self._char_before + index + len(label))) index += len(label) index += 1 return words, labels def pad(self, sent, hstart, hend): if hstart >= self._char_before: return sent, hstart, hend d = self._char_before - hstart sent = ''.join([' '] * d) + sent return sent, hstart + d, hend + d def destroy(self, *e): if self.top is None: return self.top.after_cancel(self.after) self.top.destroy() self.top = None def clear_all(self): self.query_box.delete(0, END) self.model.reset_query() self.clear_results_box() def clear_results_box(self): self.results_box['state'] = 'normal' self.results_box.delete("1.0", END) self.results_box['state'] = 'disabled' def freeze_editable(self): self.query_box['state'] = 'disabled' self.search_button['state'] = 'disabled' self.prev['state'] = 'disabled' self.next['state'] = 'disabled' def unfreeze_editable(self): self.query_box['state'] = 'normal' self.search_button['state'] = 'normal' self.set_paging_button_states() def set_paging_button_states(self): if self.current_page == 0 or self.current_page == 1: self.prev['state'] = 'disabled' else: self.prev['state'] = 'normal' if self.model.has_more_pages(self.current_page): self.next['state'] = 'normal' else: self.next['state'] = 'disabled' def fire_event(self, event): #Firing an event so that rendering of widgets happen in the mainloop thread self.top.event_generate(event, when='tail') def mainloop(self, *args, **kwargs): if in_idle(): return self.top.mainloop(*args, **kwargs)
def __init__(self, parent, app): parent.title('Trakt.tv Playback Progress Remover') self.parent = parent self.root = app self.selectedStatus = False # Widget Initialization self._listbox = Listbox( parent, font="{Segoe UI} 10", height=0, selectmode="extended", state="normal", cursor="hand2", ) self._listbox_scrollbar = AutoScrollbar(self._listbox) self._label_header = Label( parent, font="{Segoe UI} 16 bold", text="Playback items available for removal", ) self._label_actions = Label( parent, font="{Segoe UI} 14 bold", text="Actions", ) self._label_info = Label( parent, font="{Segoe UI} 14 bold", text="Info", ) self._btnRefresh = Button( parent, font="{Segoe UI} 12 bold", text="Refresh", ) self._btnRemoveSelected = Button( parent, font="{Segoe UI} 12 bold", wraplength=120, text="Remove Selected", ) self._btnSelectDeselectAll = Button( parent, font="{Segoe UI} 12 bold", wraplength=120, text="Select / Deselect All", ) self._btnLogin = Button( parent, font="{Segoe UI} 12 bold", text="Login/Auth", ) self._lbl_ID = Label( parent, font="{Segoe UI Light} 12 bold", text="ID:", ) self._lbl_Progress = Label( parent, font="{Segoe UI Light} 12 bold", text="Progress:", ) self.lbl_showName = StringVar(value="Show:") self._lbl_Show = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_showName, ) self.lbl_season = StringVar(value="Season:") self._lbl_Season = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_season, ) self.lbl_episode = StringVar(value="Episode:") self._lbl_Episode = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_episode, ) self.lbl_episodeTitle = StringVar(value="Title:") self._lbl_Title = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_episodeTitle, ) self.txt_ID = StringVar() self._txtID = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_ID, width=0, ) self.txt_progress = StringVar() self._txtProgress = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_progress, width=0, ) self.txt_showName = StringVar() self._txtShowName = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_showName, width=0, ) self.txt_season = StringVar() self._txtSeason = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_season, width=0, ) self.txt_episode = StringVar() self._txtEpisode = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_episode, width=0, ) self.txt_title = StringVar() self._txtTitle = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_title, width=0, ) self.lbl_loggedin = StringVar(value="Not logged in.") self._lbl_loggedin = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_loggedin, ) # widget commands self._listbox.bind('<<ListboxSelect>>', self._listbox_onselect) self._listbox.config(yscrollcommand=self._listbox_scrollbar.set) self._listbox_scrollbar.config(orient='vertical', command=self._listbox.yview) self._btnRefresh.configure(command=self._btn_refresh_command) self._btnRemoveSelected.configure( command=self._btn_remove_selected_command) self._btnSelectDeselectAll.configure( command=self._btn_toggle_selection_command) self._btnLogin.configure(command=self._btn_login_command) # Geometry Management self._listbox.grid(in_=parent, column=3, row=2, columnspan=1, ipadx=0, ipady=0, padx=0, pady=5, rowspan=7, sticky="nsew") self._listbox.columnconfigure(0, weight=1) self._listbox.rowconfigure(0, weight=1) self._listbox_scrollbar.grid(column=2, rowspan=7, sticky="ns") self._label_header.grid(in_=parent, column=3, row=1, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nsew") self._label_actions.grid(in_=parent, column=4, row=1, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nsew") self._label_info.grid(in_=parent, column=1, row=1, columnspan=2, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nsew") self._btnRefresh.grid(in_=parent, column=4, row=6, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=2, sticky="") self._btnRemoveSelected.grid(in_=parent, column=4, row=2, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=2, sticky="") self._btnSelectDeselectAll.grid(in_=parent, column=4, row=4, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=2, sticky="") self._btnLogin.grid(in_=parent, column=4, row=7, columnspan=1, ipadx=0, ipady=0, padx=5, pady=5, rowspan=2, sticky="es") self._lbl_ID.grid(in_=parent, column=1, row=2, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Progress.grid(in_=parent, column=1, row=3, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Show.grid(in_=parent, column=1, row=4, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Season.grid(in_=parent, column=1, row=5, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Episode.grid(in_=parent, column=1, row=6, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Title.grid(in_=parent, column=1, row=7, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._txtID.grid(in_=parent, column=2, row=2, columnspan=1, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtProgress.grid(in_=parent, column=2, row=3, columnspan=1, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtShowName.grid(in_=parent, column=2, row=4, columnspan=1, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtSeason.grid(in_=parent, column=2, row=5, columnspan=1, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtEpisode.grid(in_=parent, column=2, row=6, columnspan=1, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtTitle.grid(in_=parent, column=2, row=7, columnspan=1, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._lbl_loggedin.grid(in_=parent, column=1, row=8, columnspan=2, ipadx=0, ipady=0, padx=5, pady=5, rowspan=1, sticky="sw") # Resize Behavior parent.resizable(False, False) parent.grid_rowconfigure(1, weight=0, minsize=30, pad=20) parent.grid_rowconfigure(2, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(3, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(4, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(5, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(6, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(7, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(8, weight=0, minsize=200, pad=0) parent.grid_columnconfigure(1, weight=0, minsize=70, pad=5) parent.grid_columnconfigure(2, weight=0, minsize=450, pad=0) parent.grid_columnconfigure(3, weight=0, minsize=450, pad=0) parent.grid_columnconfigure(4, weight=0, minsize=120, pad=0)