diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e854b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*~ diff --git a/main.py b/main.py new file mode 100644 index 0000000..0839b71 --- /dev/null +++ b/main.py @@ -0,0 +1,245 @@ +import tkinter as tk +from tkinter import filedialog +from tk_tooltip import CreateToolTip +import re + +channel_names = [ + "SAY", # 0 + "SHOUT", # 1 + "TEAM", # 2 + "GUILD", # 3 +# "CIVILIZATION", # Unused +# "TERRITORY", # Unused + "UNIVERSE", # 4 + "TELL", # 5 +# "PLAYER", # Unused +# "ARROUND", # Unused + "REGION", # 6 + "DYN0", # 7 + "DYN1", # 8 + "DYN2", # 9 + "DYN3", # 10 + "DYN4", # 11 + "EMOTES", # 12 + "SYSTEM", # 13 +] + + +system_info_categories = [ + ("SYS", "Default system messages"), + ("BC", "Broadcast messages"), + ("TAGBC", "Tagged Broadcast messages"), + ("XP", "XP Gain"), + ("SP", "SP Gain"), + ("TTL", "Title"), + ("TSK", "Task"), + ("ZON", "Zone"), + ("DG", "Damage to me"), + ("DMG", "Damage to me"), + ("DGP", "Damage to me from player"), + ("DGM", "Damage from me"), + ("MIS", "Opponent misses"), + ("MISM", "I miss"), + ("ITM", "Item"), + ("ITMO", "Item other in group"), + ("ITMF", "Item failed"), + ("SPL", "Spell to me"), + ("SPLM", "Spell from me"), + ("EMT", "Emote"), + ("MTD", "Message of the day"), + ("FORLD", "Forage locate deposit"), + ("CHK", "Failed check"), + ("CHKCB", "Failed check in combat"), + ("PVPTM", "PVP Timer"), + ("THM", "Thema finished (encyclopedia)"), + ("AMB", "Ambiance (Occupation)"), + ("ISE", "Item special effect"), + ("ISE2", "Item special effect centered text"), + ("OSM", "Outpost state message"), + ("AROUND", "Around channel system message"), + ("R2_INVITE", "Ring invitation"), +] + +def get_input_filepath(): + global input_filepath + filepath = filedialog.askopenfilename( + filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")], +# initialdir='/'.join(ent_input.get().split('/')[:-1]) + ) + if not filepath: + return + input_filepath = filepath + ent_input.delete(0, tk.END) + ent_input.insert(0, input_filepath) + + +def get_output_filepath(): + global output_filepath + filepath = filedialog.askdirectory( + initialdir=ent_output.get() + ) + if not filepath: + return + output_filepath = filepath + ent_output.delete(0, tk.END) + ent_output.insert(0, output_filepath) + +def toggle_channel(index): + def tgl_chan(): + if chan_toggle[index]: + btn_chan_toggle[index].config(relief="raised") + chan_toggle[index] = False + if index == 11: + frm_btn_sys.grid_remove() + else: + btn_chan_toggle[index].config(relief="sunken") + chan_toggle[index] = True + if index == 11: + frm_btn_sys.grid() + return tgl_chan + +def toggle_system(index): + def tgl_sys(): + if sys_toggle[index]: + btn_sys_toggle[index].config(relief="raised") + sys_toggle[index] = False + else: + btn_sys_toggle[index].config(relief="sunken") + sys_toggle[index] = True + return tgl_sys + + +input_filepath = '' +output_filepath = '' +btn_chan_toggle = [] +btn_sys_toggle = [] +chan_toggle = [False] * len(channel_names) +sys_toggle = [False] * len(system_info_categories) +ent_input = None +ent_output = None +ent_outfile = None +frm_btn_sys = None + +def create_ui(): + global btn_chan_toggle + global btn_sys_toggle + global chan_toggle + global sys_toggle + global ent_input + global ent_output + global ent_outfile + global frm_btn_sys + window = tk.Tk() + window.title("Ryzom Log Cleaner") + + window.columnconfigure(0, weight=1) + #window.rowconfigure([0,1], minsize=50) + + + btn_input = tk.Button(window, text="Input file", command=get_input_filepath) + ent_input = tk.Entry(window, text="Input path") +# ent_input.insert(0, "~/log.txt") + btn_output = tk.Button(window, text="Output directory", command=get_output_filepath) + ent_output = tk.Entry(window, text="Output path") +# ent_output.insert(0, "~/cleaned/") + frm_outfile = tk.Frame(window) + lbl_outfile = tk.Label(frm_outfile, text="Output filename:") + ent_outfile = tk.Entry(frm_outfile, text="Output filename") + + btn_input.grid(row=0, column=1) + ent_input.grid(row=0, column=0, sticky='ew') + btn_output.grid(row=1, column=1) + ent_output.grid(row=1, column=0, sticky='ew') + + frm_outfile.grid(row=2, column=0, columnspan=2, sticky='ew') + frm_outfile.columnconfigure(1, weight=1) + + lbl_outfile.grid(row=0, column=0) + ent_outfile.grid(row=0, column=1, sticky='ew') + + + + lbl_channel_select = tk.Label(window, text="Select channels to keep:") + lbl_channel_select.grid(row=3, column=0, sticky='w') + + btn_chan_toggle = [] + + frm_btn_channel = tk.Frame(window) + frm_btn_channel.grid(row=4, column=0, columnspan=2, sticky='ew') + frm_btn_channel.columnconfigure([0,1,2,3], weight=1) + frm_btn_channel.rowconfigure([0,1,2], weight=1) + for i,name in enumerate(channel_names): + btn_chan_toggle.append(tk.Button(frm_btn_channel, text=name, command=toggle_channel(i))) + btn_chan_toggle[i].grid(row=int(i/4), column=i%4, sticky='ew') + + btn_sys_toggle = [] + + frm_btn_sys = tk.Frame(window, bg="#808080", borderwidth=5) + frm_btn_sys.grid(row=5, column=0, columnspan=2, sticky='e') + frm_btn_sys.columnconfigure([0,1,2,3,4,5,6], weight=1) + frm_btn_sys.rowconfigure([0,1,2,3,4], weight=1) + for i,(name,tooltip) in enumerate(system_info_categories): + btn_sys_toggle.append(tk.Button(frm_btn_sys, text=name, command=toggle_system(i))) + btn_sys_toggle[i].grid(row=int(i/7), column=i%7, sticky='ew') + ttp_sys = CreateToolTip(btn_sys_toggle[i], tooltip) + + btn_process = tk.Button(window, text="Process!", command=process_file) + btn_process.grid(row=6, column=0, columnspan=2, sticky='ew') + + # Default selection + chan_toggle = [False] * len(channel_names) + sys_toggle = [False] * len(system_info_categories) + toggle_channel(0)() + toggle_channel(1)() + toggle_channel(12)() + toggle_channel(13)() + toggle_system(7)() + + return window + +color_regex = re.compile('@\{[A-F0-9]{4}\}') +keep_color = False +keep_channel = False +language_flag = False +original_part = False +translated_part = True + +def process_file(): + chan_pattern = '|'.join(['\(' + name + '\)' for i,name in enumerate(channel_names[:-2]) if chan_toggle[i]]) + if chan_toggle[-2]: + chan_pattern += '|\(SAY/EMT\)' + if chan_toggle[-1]: + if sys_toggle[0]: + chan_pattern += '|\(SYSTEM\)' + for i,(name,tooltip) in enumerate(system_info_categories[1:]): + if sys_toggle[i+1]: + chan_pattern += '|\(SYSTEM/' + name + '\)' + chan_regex = re.compile(chan_pattern) + with open(input_filepath, 'rb') as in_file, open(output_filepath + '/' + ent_outfile.get(), 'w') as out_file: + for line in in_file: + if chan_regex.search(line) == None: + continue + if not keep_color: + line = color_regex.sub('',line) + if not keep_channel: + line = line[line.find(') * ')+4:] + translation_start = line.find('{:') + if translation_start != -1 and not language_flag: + line = line[:translation_start+1] + line[translation_start+5:] + translation_end = line.find('}@{') + if translation_end != -1 and not original_part: + line = line[:translation_start] + line[translation_end+3:] +# char_name_start = line.find(' * ') + 3 if not keep_color or line.find('}') == -1 else line.find('}') + 1 +# char_name = ' '.join(line[char_name_start:line[char_name_start:].find(':')].split(' ')[:-1]) +# if char_name[0] == '[' and char_name[2] == ']': +# char_name = char_name[3:] +# channel_name = line[21:line.find(')')] + out_file.write(line + '\n') + + +if __name__ == '__main__': + window = create_ui() + + window.mainloop() + + diff --git a/tk_tooltip.py b/tk_tooltip.py new file mode 100644 index 0000000..d973fad --- /dev/null +++ b/tk_tooltip.py @@ -0,0 +1,86 @@ +""" tk_ToolTip_class101.py +gives a Tkinter widget a tooltip as the mouse is above the widget +tested with Python27 and Python34 by vegaseat 09sep2014 +www.daniweb.com/programming/software-development/code/484591/a-tooltip-class-for-tkinter + +Modified to include a delay time by Victor Zaccardo, 25mar16 +""" + +try: + # for Python2 + import Tkinter as tk +except ImportError: + # for Python3 + import tkinter as tk + +class CreateToolTip(object): + """ + create a tooltip for a given widget + """ + def __init__(self, widget, text='widget info'): + self.waittime = 200 #miliseconds + self.wraplength = 180 #pixels + self.widget = widget + self.text = text + self.widget.bind("", self.enter) + self.widget.bind("", self.leave) + self.widget.bind("", self.leave) + self.id = None + self.tw = None + + def enter(self, event=None): + self.schedule() + + def leave(self, event=None): + self.unschedule() + self.hidetip() + + def schedule(self): + self.unschedule() + self.id = self.widget.after(self.waittime, self.showtip) + + def unschedule(self): + id = self.id + self.id = None + if id: + self.widget.after_cancel(id) + + def showtip(self, event=None): + x = y = 0 + x, y, cx, cy = self.widget.bbox("insert") + x += self.widget.winfo_rootx() + self.widget.winfo_width() - 10 + y += self.widget.winfo_rooty() + self.widget.winfo_height() - 10 + # creates a toplevel window + self.tw = tk.Toplevel(self.widget) + # Leaves only the label and removes the app window + self.tw.wm_overrideredirect(True) + self.tw.wm_geometry("+%d+%d" % (x, y)) + label = tk.Label(self.tw, text=self.text, justify='left', + background="#ffffff", relief='solid', borderwidth=1, + wraplength = self.wraplength) + label.pack(ipadx=1) + + def hidetip(self): + tw = self.tw + self.tw= None + if tw: + tw.destroy() + +# testing ... +if __name__ == '__main__': + root = tk.Tk() + btn1 = tk.Button(root, text="button 1") + btn1.pack(padx=10, pady=5) + button1_ttp = CreateToolTip(btn1, \ + 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, ' + 'consectetur, adipisci velit. Neque porro quisquam est qui dolorem ipsum ' + 'quia dolor sit amet, consectetur, adipisci velit. Neque porro quisquam ' + 'est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.') + + btn2 = tk.Button(root, text="button 2") + btn2.pack(padx=10, pady=5) + button2_ttp = CreateToolTip(btn2, \ + "First thing's first, I'm the realest. Drop this and let the whole world " + "feel it. And I'm still in the Murda Bizness. I could hold you down, like " + "I'm givin' lessons in physics. You should want a bad Vic like this.") + root.mainloop()