diff --git a/.gitignore b/.gitignore index e3cb549..48921a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.pyc TESTING.py .idea -__pycache__ \ No newline at end of file +__pycache__ +resources/config.cfg \ No newline at end of file diff --git a/__pycache__/config.cpython-35.pyc b/__pycache__/config.cpython-35.pyc index f437d40..57f22b1 100644 Binary files a/__pycache__/config.cpython-35.pyc and b/__pycache__/config.cpython-35.pyc differ diff --git a/__pycache__/ls_connection.cpython-35.pyc b/__pycache__/ls_connection.cpython-35.pyc index ad423dc..62c3619 100644 Binary files a/__pycache__/ls_connection.cpython-35.pyc and b/__pycache__/ls_connection.cpython-35.pyc differ diff --git a/__pycache__/note_reader.cpython-35.pyc b/__pycache__/note_reader.cpython-35.pyc index 2ae472a..2e69923 100644 Binary files a/__pycache__/note_reader.cpython-35.pyc and b/__pycache__/note_reader.cpython-35.pyc differ diff --git a/config.py b/config.py index bfb55de..4894992 100644 --- a/config.py +++ b/config.py @@ -64,7 +64,7 @@ TEXT_FILES = [ ] # Default content of config.cfg file -DEFAULT_CONFIG = "notes=\nfont_size=12\nfont=arial\ntext_color=#FFFFFF\nbackground_color=#000000\nserver_port=16834" +DEFAULT_CONFIG = "notes=\nfont_size=12\nfont=arial\ntext_color=#000000\nbackground_color=#FFFFFF\ndouble_layout=False\nserver_port=16834" # Required settings REQUIRED_SETTINGS = ("notes", @@ -72,13 +72,14 @@ REQUIRED_SETTINGS = ("notes", "font_size", "text_color", "background_color", - "server_port" + "server_port", + "double_layout" ) # Settings window options SETTINGS_WINDOW = {"TITLE": "Settings", "WIDTH": 360, - "HEIGHT": 280, + "HEIGHT": 330, "CANCEL": "Cancel", "SAVE": "Save"} @@ -88,12 +89,12 @@ SETTINGS_OPTIONS = {"FONT": "Font", "TEXT_COLOR": "Text Color", "BG_COLOR": "Background Color", "SERVER_PORT": "LiveSplit Server port", - "DEFAULT_SERVER_PORT": "(Default is 16834)"} + "DEFAULT_SERVER_PORT": "(Default is 16834)", + "DOUBLE_LAYOUT": "Use double layout"} # Fonts that can be selected AVAILABLE_FONTS = ("arial", "courier new", - "comic sans", "fixedsys", "ms sans serif", "ms serif", diff --git a/ls_connection.py b/ls_connection.py index 705dc3d..a607f03 100644 --- a/ls_connection.py +++ b/ls_connection.py @@ -8,9 +8,9 @@ import config import select # used for checking if socket has data pending -def ls_connect(ls_socket, call_func, window): +def ls_connect(ls_socket, call_func, window, server_port): """Connects given socket to the livesplit server.""" - con_thread = Thread(target=try_connection, args=(ls_socket, call_func, window)) + con_thread = Thread(target=try_connection, args=(ls_socket, call_func, window, server_port)) con_thread.start() @@ -19,7 +19,7 @@ def init_socket(): return socket.socket() -def try_connection(ls_socket, call_func, window): +def try_connection(ls_socket, call_func, window, server_port): """ Tries to connect given socket to ls. If connection is successful given "call_func" @@ -27,7 +27,7 @@ def try_connection(ls_socket, call_func, window): (made to be ran in a separate thread) """ try: - ls_socket.connect((config.HOST, config.PORT)) + ls_socket.connect((config.HOST, server_port)) except: return False diff --git a/main_window.py b/main_window.py index e1f027f..d4c9fce 100644 --- a/main_window.py +++ b/main_window.py @@ -9,16 +9,15 @@ import sys import config import ls_connection as con import note_reader as noter -import setting_handler as settings +import setting_handler runtime_info = { "ls_connected": False, "timer_running": False, - "icon_active": False, "active_split": -1, "notes": [], - "double_layout": False, - "big_font": False + "server_port": 0, + "force_reset": False } root = tkinter.Tk() @@ -41,9 +40,14 @@ def update(window, com_socket, text1, text2): """ Function to loop along tkinter mainloop. """ - if not runtime_info["ls_connected"]: + if runtime_info["force_reset"]: + #boolean flag to force a connection reset + com_socket = reset_connection(com_socket, window, text1, text2) + runtime_info["force_reset"] = False + + elif not runtime_info["ls_connected"]: # try connecting to ls - con.ls_connect(com_socket, server_found, window) + con.ls_connect(com_socket, server_found, window, runtime_info["server_port"]) else: # is_connected if runtime_info["notes"]: @@ -105,7 +109,7 @@ def update_GUI(window, com_socket, text1, text2): if runtime_info["notes"]: set_title_notes(window, index, split_name) - update_notes(window, text1, text2, index) + update_notes(text1, text2, index) else: update_title(config.DEFAULT_WINDOW["TITLE"], window) @@ -139,6 +143,7 @@ def reset_connection(com_socket, window, text1, text2): # Close old and return a fresh socket con.close_socket(com_socket) + return con.init_socket() @@ -153,12 +158,10 @@ def server_found(window): def update_icon(active, window): """Updates icon of window depending on "active" variable""" - if active and not runtime_info["icon_active"]: + if active: window.tk.call('wm', 'iconphoto', window._w, green_icon) - runtime_info["icon_active"] = True - elif runtime_info["icon_active"]: + else: window.tk.call('wm', 'iconphoto', window._w, red_icon) - runtime_info["icon_active"] = False def update_title(name, window): @@ -205,16 +208,6 @@ def show_popup(event, menu): menu.post(event.x_root, event.y_root) -def menu_change_layout(window, box1, box2, popup): - """Menu option for changing layout selected.""" - if runtime_info["double_layout"]: - set_single_layout(window, box1, box2) - popup.entryconfig(0, label=config.MENU_OPTIONS["DOUBLE"]) - else: - set_double_layout(window, box1, box2) - popup.entryconfig(0, label=config.MENU_OPTIONS["SINGLE"]) - - def menu_load_notes(window, text1, text2, com_socket): """Menu selected load notes option.""" load_notes(window, text1, text2, com_socket) @@ -232,6 +225,11 @@ def load_notes(window, text1, text2, com_socket): # Notes loaded correctly runtime_info["notes"] = notes + # Save notes to settings + settings = setting_handler.load_settings() + settings["notes"] = file + setting_handler.save_settings(settings) + split_c = len(notes) show_info(("Notes Loaded", ("Loaded notes with " + str(split_c) + " splits."))) @@ -244,10 +242,9 @@ def load_notes(window, text1, text2, com_socket): else: show_info(config.ERRORS["NOTES_EMPTY"], True) - def show_info(info, warning=False): """ - Displays an infor popup window. + Displays an info popup window. if warning is True window has a warning triangle. """ if warning: @@ -256,7 +253,7 @@ def show_info(info, warning=False): messagebox.showinfo(info[0], info[1]) -def update_notes(window, text1, text2, index): +def update_notes(text1, text2, index): """ Displays notes with the given index in given text widgets. If index is lower than 0, displays notes for index 0. @@ -279,7 +276,7 @@ def update_notes(window, text1, text2, index): if index <= max_index: text1.insert(tkinter.END, runtime_info["notes"][index]) - # cand disply notes for index+1 + # cant disply notes for index+1 if index < max_index: text2.insert(tkinter.END, runtime_info["notes"][index + 1]) @@ -298,7 +295,10 @@ def left_arrow(window, com_socket, text1, text2): def change_preview(window, com_socket, text1, text2, move): - """move is either 1 for next or -1 for previous.""" + """ + Chnges notes that are currently displayed. + Move is either 1 for next or -1 for previous. + """ if runtime_info["notes"] and (not runtime_info["timer_running"]): max_index = (len(runtime_info["notes"]) - 1) index = runtime_info["active_split"] @@ -334,34 +334,31 @@ def set_title_notes(window, index, split_name=False): update_title(title, window) -def menu_font_size(text_font, menu): - if runtime_info["big_font"]: - runtime_info["big_font"] = False - menu.entryconfig(1, label=config.MENU_OPTIONS["BIG"]) +def menu_open_settings(root_wnd, box1, box2, text1, text2): + setting_handler.edit_settings(root_wnd, + (lambda settings: apply_settings(settings, + root_wnd, + box1,box2, + text1, text2))) + + +def apply_settings(settings, window, box1, box2, text1, text2): + #Server port change + if not (runtime_info["server_port"] == int(settings["server_port"])): + runtime_info["server_port"] = int(settings["server_port"]) + runtime_info["force_reset"] = True + + text_font = (settings["font"], int(settings["font_size"])) + + if setting_handler.decode_boolean_setting(settings["double_layout"]): + set_double_layout(window, box1, box2) else: - runtime_info["big_font"] = True - menu.entryconfig(1, label=config.MENU_OPTIONS["SMALL"]) + set_single_layout(window, box1, box2) - update_font_size(text_font) - - -def menu_open_settings(root_wnd, apply_method, text1, text2): - settings.edit_settings(root_wnd, (lambda settings: apply_settings(settings, text1, text2))) - - -def apply_settings(config, text1, text2): - # TODO apply all settings to the root window - print("Applying settings") - print(config) - - -def update_font_size(text_font): - if runtime_info["big_font"]: - font_size = config.FONT["BIG"] - else: - font_size = config.FONT["SMALL"] - - text_font.config(size=font_size) + text1.config(font=text_font) + text2.config(font=text_font) + text1.config(fg=settings["text_color"], bg=settings["background_color"]) + text2.config(fg=settings["text_color"], bg=settings["background_color"]) def init_UI(root): @@ -370,6 +367,10 @@ def init_UI(root): # Create communication socket com_socket = con.init_socket() + # Load Settings + settings = setting_handler.load_settings() + runtime_info["server_port"] = int(settings["server_port"]) + # Graphical components root.geometry(str(config.DEFAULT_WINDOW["WIDTH"]) + "x" + str(config.DEFAULT_WINDOW["HEIGHT"])) @@ -392,6 +393,7 @@ def init_UI(root): text1.config(state=tkinter.DISABLED) text1.pack(fill=tkinter.BOTH, expand=True) + text2 = tkinter.Text( box2, yscrollcommand=scroll2.set, @@ -406,44 +408,43 @@ def init_UI(root): scroll2.config(command=text2.yview) # Set font and color for text - text_font = font.Font( - family=config.FONT["NAME"], - size=config.FONT["SMALL"] - ) + text_font = (settings["font"], int(settings["font_size"])) + text1.config(font=text_font) text2.config(font=text_font) - text1.config(fg=config.COLOR["TEXT"], bg=config.COLOR["TEXT_BG"]) - text2.config(fg=config.COLOR["TEXT"], bg=config.COLOR["TEXT_BG"]) + text1.config(fg=settings["text_color"], bg=settings["background_color"]) + text2.config(fg=settings["text_color"], bg=settings["background_color"]) - set_single_layout(root, box1, box2) + if setting_handler.decode_boolean_setting(settings["double_layout"]): + set_double_layout(root, box1, box2) + else: + set_single_layout(root, box1, box2) # create popup menu popup = tkinter.Menu(root, tearoff=0) - popup.add_command( - label=config.MENU_OPTIONS["DOUBLE"], - command=( - lambda: menu_change_layout(root, box1, box2, popup) - ) - ) # Needs to be at index 0 - popup.add_command( - label=config.MENU_OPTIONS["BIG"], - command=( - lambda: menu_font_size(text_font, popup) - ) - ) # Needs to be at index 1 popup.add_command( label=config.MENU_OPTIONS["LOAD"], command=(lambda: menu_load_notes(root, text1, text2, com_socket)) ) popup.add_command( label=config.MENU_OPTIONS["SETTINGS"], - command=(lambda: menu_open_settings(root, apply_settings, text1, text2)) + command=(lambda: menu_open_settings(root, box1, box2, text1, text2)) ) # Set default window icon and title root.tk.call('wm', 'iconphoto', root._w, red_icon) update_title(config.DEFAULT_WINDOW["TITLE"], root) + # Check if notes can be loaded from settings + settings = setting_handler.load_settings() + + if settings["notes"] and noter.file_exists(settings["notes"]): + notes = noter.get_notes(settings["notes"]) + + if notes: + runtime_info["notes"] = notes + update_GUI(root, com_socket, text1, text2) + # Event binds root.bind("", (lambda e: adjust_content(root, box1, box2))) root.bind("", (lambda e: show_popup(e, popup))) diff --git a/note_reader.py b/note_reader.py index a0b431f..211a263 100644 --- a/note_reader.py +++ b/note_reader.py @@ -120,3 +120,7 @@ def select_file(): return file else: return False + + +def file_exists(file): + return path.isfile(file) \ No newline at end of file diff --git a/resources/config.cfg b/resources/config.cfg index 05e2cfa..f3580f3 100644 --- a/resources/config.cfg +++ b/resources/config.cfg @@ -1,6 +1,7 @@ -notes= -font=times new roman -font_size=12 -server_port=34 -background_color=#4d73f4 -text_color=#ff8080 +notes=C:/Users/Joel/Documents/EA Games/Mirror's Edge/TdGame/Config/TdEngine.ini +server_port=16834 +text_color=#000000 +double_layout=True +font_size=11 +font=ms sans serif +background_color=#ffffff diff --git a/setting_handler.py b/setting_handler.py index e84ba07..01ba985 100644 --- a/setting_handler.py +++ b/setting_handler.py @@ -18,6 +18,7 @@ settings_icon_path = os.path.join( config.ICONS["SETTINGS"] ) + def load_settings(): """ Tries to load settings from file. @@ -65,10 +66,11 @@ def format_settings(file_rows): for row in file_rows: row = row.strip("\n") - parts = row.split("=") + parts = row.split("=", 1) if len(parts) == SETTING_PART_LENGTH: - settings[parts[0]] = parts[1] + # Strip to remove whitespace at end and beginning + settings[parts[0].strip()] = parts[1].strip() return settings @@ -115,6 +117,10 @@ def validate_settings(settings): if not (settings["font"] in config.AVAILABLE_FONTS): return False + if not ((settings["double_layout"] == "True") or + (settings["double_layout"] == "False")): + return False + return True @@ -156,6 +162,9 @@ def edit_settings(root_wnd, apply_method): bg_color_label = tkinter.Label(settings_wnd, text=config.SETTINGS_OPTIONS["BG_COLOR"], font=config.GUI_FONT) + layout_label = tkinter.Label(settings_wnd, + text=config.SETTINGS_OPTIONS["DOUBLE_LAYOUT"], + font=config.GUI_FONT) port_label = tkinter.Label(settings_wnd, text=config.SETTINGS_OPTIONS["SERVER_PORT"], font=config.GUI_FONT) @@ -163,6 +172,7 @@ def edit_settings(root_wnd, apply_method): text=config.SETTINGS_OPTIONS["DEFAULT_SERVER_PORT"], font=config.GUI_FONT) + # Font Selection selected_font = tkinter.StringVar(settings_wnd) selected_font.set(settings["font"]) @@ -211,7 +221,6 @@ def edit_settings(root_wnd, apply_method): def bg_color_selection(): choosen_color = colorchooser.askcolor() if choosen_color[1]: - print(choosen_color) settings["background_color"] = choosen_color[1] bg_color.configure(background=settings["background_color"]) @@ -223,6 +232,13 @@ def edit_settings(root_wnd, apply_method): port_entry = tkinter.Entry(settings_wnd, width=6, font=config.GUI_FONT) port_entry.insert(0, settings["server_port"]) + # Double Layout Selection + double_layout = tkinter.BooleanVar() + double_layout_btn = tkinter.Checkbutton(settings_wnd, variable=double_layout) + + if decode_boolean_setting(settings["double_layout"]): + double_layout_btn.select() + # Save and cancel buttons def control_and_save(): errors_found = False @@ -232,6 +248,8 @@ def edit_settings(root_wnd, apply_method): chosen_font_size = font_size_entry.get() chosen_port = port_entry.get() + settings["double_layout"] = encode_boolean_setting(double_layout.get()) + if not validate_font_size(chosen_font_size): msgbox.showerror(config.ERRORS["FONT_SIZE"][0], config.ERRORS["FONT_SIZE"][1]) errors_found = True @@ -265,17 +283,19 @@ def edit_settings(root_wnd, apply_method): font_size_label.place(x=15, y=55) text_color_label.place(x=15, y=95) bg_color_label.place(x=15, y=135) - port_label.place(x=15, y=175) - default_port_label.place(x=15, y=200) + layout_label.place(x=15, y=175) + port_label.place(x=15, y=215) + default_port_label.place(x=15, y=240) font_dropdown.place(x=178, y=15) font_size_entry.place(x=180, y=55) text_color.place(x=180, y=95) bg_color.place(x=180, y=135) - port_entry.place(x=180, y=175) + double_layout_btn.place(x=180, y=175) + port_entry.place(x=180, y=215) - save_btn.place(x=110, y=230) - cancel_btn.place(x=190, y=230) + save_btn.place(x=110, y=280) + cancel_btn.place(x=190, y=280) def validate_color(color): @@ -314,4 +334,14 @@ def save_settings(settings): for key in settings.keys(): file_content += key + "=" + settings[key] + "\n" - set_settings_file_content(file_content) \ No newline at end of file + set_settings_file_content(file_content) + + +def decode_boolean_setting(setting): + return setting == "True" + +def encode_boolean_setting(value): + if value: + return "True" + else: + return "False"