class TextWindow(tk.Toplevel): def __init__(self, parent, view=None, font=fm.text_font, title='', wrap=tk.WORD, *args, **kwargs): tk.Toplevel.__init__(self, parent.root, *args, **kwargs) self.parent = parent self.title(title) # self.results = None self.results = [] self.complete = True self.order = [True, False, True, True, False] self.rows_n = 0 if view is not None: inst = self.parent.instructions.get(view) instructions_frame = tk.Frame(self) self.instructions_lbl = tk.Label(instructions_frame, text=inst, justify=tk.LEFT) self.instructions_lbl.bind("<Configure>", self.set_label_wrap) self.instructions_lbl.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X) instructions_frame.pack(side=tk.TOP, expand=tk.YES, fill=tk.X) top_frame = tk.Frame(self) self.text = FancyText(top_frame, gui_obj=self.parent, wrap=wrap, padx=10, pady=5, font=font) self.text.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH) self.text.tag_config('text_bg', background=fm.text_bg) self.text.tag_config('white', background=fm.white) self.text.tag_config('heading', font=fm.bold_ms_font) # give priority to formatting of selected text over that of tags self.text.tag_raise('sel') self.text.tag_bind('heading', '<Button-1>', self.heading_click) self.vsb = tk.Scrollbar(top_frame) self.vsb.pack(side=tk.RIGHT, fill=tk.Y) self.vsb.config(command=self.text.yview) self.text.config(yscrollcommand=self.vsb.set) top_frame.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH) def set_label_wrap(self, event): wraplength = event.width - 12 # 12, to account for padding and borderwidth event.widget.configure(wraplength=wraplength) def add_result(self, result): self.text.insert(tk.END, result.row(), fm.list_bgs[self.rows_n % 2]) self.results.append(result) self.rows_n += 1 def heading_click(self, event, tag='heading'): if self.complete: # get the index of the mouse click index = self.text.index("@%s,%s" % (event.x, event.y)) # get the indices of all "adj" tags tag_indices = list(self.text.tag_ranges('heading')) # iterate them pairwise (start and end index) for start, end in zip(tag_indices[0::2], tag_indices[1::2]): # check if the tag matches the mouse click index if self.text.compare(start, '<=', index) and self.text.compare( index, '<', end): # return string between tag start and end clicked_heading = self.text.get(start, end) for i, h in enumerate(self.results[0].heading()): if clicked_heading.startswith(h): self.text.delete(2.0, tk.END) self.text.insert(tk.END, '\n\n') self.order[i] = not self.order[i] for k, res in enumerate( sorted(self.results, key=attrgetter(Result.attrs[i]), reverse=self.order[i])): self.text.insert(tk.END, res.row(), fm.list_bgs[k % 2]) break
class ConcWindow(tk.Toplevel): max_center_len= 0 def __init__(self, parent, query, corpus, id, save, tokens_left, instructions=None, *args, **kwargs): tk.Toplevel.__init__(self, parent.root, *args, **kwargs) self.query = query self.parent = parent self.corpus = corpus self.id = id self.title('Results for ' + query) self.tokens_left = tokens_left self.geometry('1200x550') self.center_inds = [] self.text_locs = [] self.bind('<Double-Button-1>', self.db_click) inst = self.parent.instructions.get('Concordance Window') if inst: instructions_frame = tk.Frame(self) self.instructions_lbl = tk.Label(instructions_frame, text=inst, justify=tk.LEFT) self.instructions_lbl.bind("<Configure>", self.set_label_wrap) self.instructions_lbl.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X) instructions_frame.pack(side=tk.TOP, expand=tk.YES, fill=tk.X) conc_frame = tk.Frame(self) self.text = FancyText(conc_frame, gui_obj=self.parent, wrap='none', font=fm.ms_font) self.text.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH) vsb = tk.Scrollbar(conc_frame) vsb.pack(side=tk.RIGHT, fill=tk.Y) vsb.config(command=self.text.yview) self.text.config(yscrollcommand=vsb.set) conc_frame.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH) hsb = tk.Scrollbar(self, orient='horizontal') hsb.pack(fill=tk.X, side=tk.BOTTOM) hsb.config(command=self.text.xview) self.text.config(xscrollcommand=hsb.set) menu_bar = tk.Menu(self) file_menu = tk.Menu(menu_bar, tearoff=0) file_menu.add_command(label="Save", command=lambda: save(self.text.get(1.0, tk.END), self.max_center_len, self.tokens_left)) menu_bar.add_cascade(label="File", menu=file_menu) self.config(menu=menu_bar) def set_label_wrap(self, event): wraplength = event.width - 12 # 12, to account for padding and borderwidth event.widget.configure(wraplength=wraplength) def db_click(self, event): ins_ind = self.text.index(tk.INSERT) row, col = str(ins_ind).split('.') row, col = int(row), int(col) w_left, w_right = self.center_inds[row - 1] if w_right > col > w_left: left_i, right_i, text_i = self.text_locs[row-1] self.show_context(left_i, right_i, text_i) def show_context(self, left_i, right_i, text_i): t = self.corpus.texts[text_i].text text_window = TextWindow(self.parent, title=self.corpus.texts[text_i].filepath) text_window.text.tag_config('highlight', foreground='red') text_window.text.tag_config('context', background='yellow') # gets indices from text that has been clicked on single_text_locs = [item for item in self.text_locs if item[-1] == text_i] # adds text coming before first match if single_text_locs[0][0] > 0: text_window.text.insert(tk.END, t[:single_text_locs[0][0]]) # highlights matches and adds text between match i and the following match for i, (ltl, rtl, _) in enumerate(single_text_locs): if ltl == left_i: text_window.text.insert(tk.END, t[ltl:rtl], 'context') text_window.text.see(tk.END) else: text_window.text.insert(tk.END, t[ltl:rtl], 'highlight') if len(t) > rtl + 1: if len(single_text_locs) > i + 1: text_window.text.insert(tk.END, t[rtl:single_text_locs[i+1][0]]) else: text_window.text.insert(tk.END, t[rtl:])