def process(): unitex_path = up_bar.get(1.0, END).rstrip("\n") text_path = tp_bar.get(1.0, END).rstrip("\n") lang = selected_lang.get() self._nulitek = Nulitek(unitex_path, text_path, lang) if preprocess_text.get(): self._nulitek.processText(convert_text.get()) # Saves data with open(CONFIG_FILE, 'w') as f: f.write(unitex_path + '\n') f.write(text_path + '\n') f.write(lang + '\n') popup.destroy()
class NulitekGUI: """ Graphical user interface for NuLiTeK """ def __init__(self): self._nulitek = None self._root = Tk() self._root.title("NuLiTeK") self._mainframe = Frame(self._root) self._mainframe.pack() # Menus self._menubar = Menu(self._root) self._root.config(menu=self._menubar) self._menubar.add_command(label="Settings", command=self.init_Nulitek) self._menubar.add_command(label="Help", command=self.help) # Title Label(self._mainframe, text="NuLiTeK", font=("Helvetica", "40", "bold")).pack(side=TOP) # Research bar research_frame = Frame(self._mainframe) research_frame.pack(side=TOP, anchor=N) self._searchbar = Text(research_frame, height=1, width=88) self._searchbar.pack(side=LEFT, anchor=W, padx=10) self._searchbar.bind("<Return>", lambda x : self._search(self._searchbar.get(1.0, END).rstrip('\r\n'))) Button(research_frame, text="Rechercher", command= lambda: self._search(self._searchbar.get(1.0, END).rstrip('\r\n'))).pack(side=RIGHT, anchor=E) Frame(self._mainframe, bg="grey").pack(side=TOP, fill=X, padx=40, pady=10) # Matches self._full_req = StringVar() match_frame = Frame(self._mainframe) match_frame.pack(side=TOP, anchor=N) Label(match_frame, textvariable=self._full_req).pack(side=TOP, anchor=N, fill=X) self._matchbox = Text(match_frame, state=DISABLED, width=88, height=20) self._matchbox.pack(side=TOP, anchor=N, fill=X, padx=3, pady=10) self.init_Nulitek() def init_Nulitek(self): """ Loads the Unitex dictionnary, and loads and preprocesses text """ def process(): unitex_path = up_bar.get(1.0, END).rstrip("\n") text_path = tp_bar.get(1.0, END).rstrip("\n") lang = selected_lang.get() self._nulitek = Nulitek(unitex_path, text_path, lang) if preprocess_text.get(): self._nulitek.processText(convert_text.get()) # Saves data with open(CONFIG_FILE, 'w') as f: f.write(unitex_path + '\n') f.write(text_path + '\n') f.write(lang + '\n') popup.destroy() def fill_field(field, data): field.delete(1.0, END) field.insert(END, data) # Read data popup = Toplevel(self._mainframe, takefocus=True) preprocess_text = BooleanVar() convert_text = BooleanVar() selected_lang = StringVar() up_frame = Frame(popup) up_frame.pack(side=TOP, anchor=W) Label(up_frame, text="Unitex path : ").pack(side=LEFT) up_bar = Text(up_frame, height=1) up_bar.pack(side=LEFT, fill=X) Button(up_frame, text='...', command= lambda:fill_field(up_bar, filedialog.askdirectory( parent=popup, initialdir='.', title="Select the Unitex lang directory"))).pack(side=LEFT) tp_frame = Frame(popup) tp_frame.pack(side=TOP, anchor=W) Label(tp_frame, text="Path to text :").pack(side=LEFT) tp_bar = Text(tp_frame, height=1) tp_bar.pack(side=LEFT, fill=X) Button(tp_frame, text='...', command= lambda:fill_field(tp_bar, filedialog.askopenfilename( parent=popup, initialdir='.', title="Select the text"))).pack(side=LEFT) lang_frame = Frame(popup) lang_frame.pack(side=TOP, anchor=W) Label(lang_frame, text="Language :").pack(side=LEFT) OptionMenu(lang_frame, selected_lang, *AVAILABLE_LANGS).pack(side=TOP) opt_frame = Frame(popup) opt_frame.pack(side=TOP, anchor=W) Checkbutton(opt_frame, variable=preprocess_text, text="Preprocess text", offvalue=False, onvalue=True).pack(side=LEFT, anchor=N) Checkbutton(opt_frame, variable=convert_text, text="Convert to UTF-16", offvalue=False, onvalue=True).pack(side=LEFT, anchor=N) Button(popup, text="OK", command=process).pack(side=TOP, anchor=N) # Loads default data if exists try: with open(CONFIG_FILE, 'r') as f: unitex_path = f.readline().rstrip('\r\n') text_path = f.readline().rstrip('\r\n') lang = f.readline().rstrip('\r\n') up_bar.insert(END, unitex_path) tp_bar.insert(END, text_path) selected_lang.set(lang) except FileNotFoundError: pass def mainloop(self): self._root.mainloop() def _search(self, text): """ Deploys and searches a custom regular expression on the selected document text -- the request to process """ if not text: raise EmptySearchException if not self._nulitek: self.init_Nulitek() self._searchbar.delete(1.0, END) req = self._nulitek.developRequest(text) res = self._nulitek.makeRequest(req) self._full_req.set(req) self._matchbox.tag_config("highlight", background="yellow") self._matchbox.config(state=NORMAL) self._matchbox.delete(1.0, END) if not res: self._matchbox.insert(END, "No match found for %s" % text) line = 1 for (prefix, match, suffix) in res: self._matchbox.insert(END, prefix + " " + match + " " + suffix + "\n") self._matchbox.tag_add("highlight", "%s.%s" % (line, len(prefix) + 1), "%s.%s" % (line, len(prefix) + len(match) + 1)) line += 1 self._matchbox.config(state=DISABLED) pass def help(self): """ Displays an help pop-up """ help_text = """ # NuLiTeK A software by Théo Le Calvar & Alexis Braine Cet utilitaire fusionne les capacités de recherches d'Unitex à la gestion des sens de Wordnet. Grâce à NuLiTeK, vous pourrez facilement effectuer des recherches concernant la structure ainsi que les sens des phrases. Par exemple Igor {SYN:embraser} <DET> <N> permettra de trouver ce à quoi Igor vient de mettre feu. Lors du lancement de l'interface graphique il vous est nécessaire de configurer NuLiTeK avec les chemins du dossier de langue d'Unitex à utiliser, le fichier texte à traiter (ce fichier texte devra être en UTF-8 ou UTF-16LE, dans le premier cas il est possible de le convertir via une case à cocher) ainsi que la langue à utiliser pour NLTK. Une fois fait vous arriverez sur la fenêtre principale, vous pourrez y entrer vos requêtes dans le champs texte du haut et visualiser les résultats dans la zone inférieure. # Structure du langage de requête Le langage de requête utilisé par NuLiTeK est basé sur celui d'Unitex, il est donc tout à fait possible d'utiliser toutes les possibilité de celui ci dans NuLiTeK. Aux balises d'Unitex s'ajoutent des marqueurs de la forme {Action:Argument,Unitex} , où Action est l'un des mots clefs suivant : - HPR : seront reconnus les hypernymes de l'argument passé à la balises - HPO : reconnait les hyponymes de l'argument - SYN : reconnait synonymes de l'argument La partie Unitex du marqueur sert à ajouter des informations propre à Unitex aux mots recherchés. On traduira {HPR:cheval,N} par les hypernymes de "cheval" qui sont des noms. Il faut noter qu'une des limitations actuelle nous empèche de traiter des requêtes ayant des marqueurs ayant trop de sens. Par exemple utiliser {SYN:faire} conduira à un temps de génération du graphe de requete très important. """ popup = Toplevel(self._mainframe, takefocus=True) popup.title("Help !") Label(popup, text=help_text, justify=LEFT).pack(side=TOP, anchor=W, fill=X) Button(popup, text="OK", command=popup.destroy).pack(side=TOP, anchor=N)