From 91d71308dfd21b38ae07b9796d198a37ec2f8c64 Mon Sep 17 00:00:00 2001 From: Joelnir Date: Fri, 15 Apr 2016 21:16:34 +0200 Subject: [PATCH] Added formatting options Added the option to use another split separator than newline. Also removed stripping of spaces at the beginning and end of lines of notes. --- config.py | 18 ++++++++---- main_window.py | 40 +++++++++++++++++++++----- note_reader.py | 27 ++++++++++------- setting_handler.py | 72 +++++++++++++++++++++++++++++++++++++++------- 4 files changed, 123 insertions(+), 34 deletions(-) diff --git a/config.py b/config.py index 8ad5b06..8bfcd61 100644 --- a/config.py +++ b/config.py @@ -44,7 +44,8 @@ MENU_OPTIONS = { # Error messages ERRORS = {"NOTES_EMPTY": ("Error!", "Notes empty or can't be loaded!"), "FONT_SIZE": ("Error!", "Invalid Font Size!"), - "SERVER_PORT": ("Error!", "Invalid server port!")} + "SERVER_PORT": ("Error!", "Invalid server port!"), + "SEPARATOR": ("Error!", "Invalid split separator!")} # Max file size for notes MAX_FILE_SIZE = 1000000000 # 1 Giga-Byte @@ -62,7 +63,9 @@ TEXT_FILES = [ ] # Default content of config.cfg file -DEFAULT_CONFIG = "notes=\nfont_size=12\nfont=arial\ntext_color=#000000\nbackground_color=#FFFFFF\ndouble_layout=False\nserver_port=16834\nwidth=400\nheight=300" +DEFAULT_CONFIG = "notes=\nfont_size=12\nfont=arial\ntext_color=#000000\nbackground_color=#FFFFFF\ndouble_layout=False\nserver_port=16834\nwidth=400\nheight=300\nseparator=new_line" + +NEWLINE_CONSTANT = "new_line" # Required settings REQUIRED_SETTINGS = ("notes", @@ -73,13 +76,14 @@ REQUIRED_SETTINGS = ("notes", "server_port", "double_layout", "width", - "height" + "height", + "separator" ) # Settings window options SETTINGS_WINDOW = {"TITLE": "Settings", "WIDTH": 360, - "HEIGHT": 330, + "HEIGHT": 410, "CANCEL": "Cancel", "SAVE": "Save"} @@ -90,7 +94,9 @@ SETTINGS_OPTIONS = {"FONT": "Font", "BG_COLOR": "Background Color", "SERVER_PORT": "LiveSplit Server port", "DEFAULT_SERVER_PORT": "(Default is 16834)", - "DOUBLE_LAYOUT": "Use double layout"} + "DOUBLE_LAYOUT": "Use double layout", + "NEW_LINE_SEPARATOR": "Newline as split separator", + "CUSTOM_SEPARATOR": "Custom split separator"} # Fonts that can be selected AVAILABLE_FONTS = ("arial", @@ -100,4 +106,4 @@ AVAILABLE_FONTS = ("arial", "ms serif", "system", "times new roman", - "verdana") + "verdana") \ No newline at end of file diff --git a/main_window.py b/main_window.py index e95e5c4..1c02d7c 100644 --- a/main_window.py +++ b/main_window.py @@ -16,7 +16,8 @@ runtime_info = { "notes": [], "server_port": 0, "force_reset": False, - "double_layout": False + "double_layout": False, + "settings": {} } root = tkinter.Tk() @@ -219,7 +220,7 @@ def load_notes(window, text1, text2, com_socket): file = noter.select_file() if file: - notes = noter.get_notes(file) + notes = noter.get_notes(file, runtime_info["settings"]["separator"]) if notes: # Notes loaded correctly runtime_info["notes"] = notes @@ -334,7 +335,7 @@ def set_title_notes(window, index, split_name=False): update_title(title, window) -def menu_open_settings(root_wnd, box1, box2, text1, text2): +def menu_open_settings(root_wnd, box1, box2, text1, text2, com_socket): """ Opens the settings menu. """ @@ -342,14 +343,16 @@ def menu_open_settings(root_wnd, box1, box2, text1, text2): (lambda settings: apply_settings(settings, root_wnd, box1, box2, - text1, text2))) + text1, text2, com_socket))) -def apply_settings(settings, window, box1, box2, text1, text2): +def apply_settings(settings, window, box1, box2, text1, text2, com_socket): """ Applies the given settings to the given components. Settings must be a correctly formatted dictionary. """ + runtime_info["settings"] = settings + # Server port change if not (runtime_info["server_port"] == int(settings["server_port"])): runtime_info["server_port"] = int(settings["server_port"]) @@ -367,6 +370,28 @@ def apply_settings(settings, window, box1, box2, text1, text2): text1.config(fg=settings["text_color"], bg=settings["background_color"]) text2.config(fg=settings["text_color"], bg=settings["background_color"]) + old_note_length = len(runtime_info["notes"]) + + if settings["notes"] and noter.file_exists(settings["notes"]): + new_notes = noter.get_notes(settings["notes"], settings["separator"]) + + if new_notes: + # Notes loaded correctly + runtime_info["notes"] = new_notes + + new_note_length = len(new_notes) + + if not (new_note_length == old_note_length): + show_info(("Notes Loaded", + ("Loaded notes with " + str(new_note_length) + " splits."))) + + if not runtime_info["timer_running"]: + runtime_info["active_split"] = -1 + + update_GUI(window, com_socket, text1, text2) + else: + show_info(config.ERRORS["NOTES_EMPTY"], True) + def save_geometry_settings(width, height): """ @@ -397,6 +422,7 @@ def init_UI(root): # Load Settings settings = setting_handler.load_settings() runtime_info["server_port"] = int(settings["server_port"]) + runtime_info["settings"] = settings # Graphical components root.geometry(settings["width"] + "x" + settings["height"]) @@ -453,7 +479,7 @@ def init_UI(root): ) popup.add_command( label=config.MENU_OPTIONS["SETTINGS"], - command=(lambda: menu_open_settings(root, box1, box2, text1, text2)) + command=(lambda: menu_open_settings(root, box1, box2, text1, text2, com_socket)) ) # Set default window icon and title @@ -464,7 +490,7 @@ def init_UI(root): settings = setting_handler.load_settings() if settings["notes"] and noter.file_exists(settings["notes"]): - notes = noter.get_notes(settings["notes"]) + notes = noter.get_notes(settings["notes"], settings["separator"]) if notes: runtime_info["notes"] = notes diff --git a/note_reader.py b/note_reader.py index 85fea47..f0edefe 100644 --- a/note_reader.py +++ b/note_reader.py @@ -5,9 +5,10 @@ import config """ NOTE STANDARD FORMATTING - empty newlines separate notes for different splits +It is also possible to set your own split separator in the settings menu + lines that start and end with [ ] are ignored for notes. these can be used for titles. (ex. [Split1] is not included in notes) @@ -50,21 +51,29 @@ def get_note_lines(file_path): return f_lines -def encode_notes(note_lines): +def decode_notes(note_lines, separator): """ Takes a list containing strings. Encodes given strings according to the note formatting. Returns the list containing the notes for every split. """ + #Check if newline is being used as separator + + if separator == config.NEWLINE_CONSTANT: + separator = "" # left after stripping newline + def is_title(line): if not line: return False return (line[0] == "[") and (line[-1] == "]") - def is_newline(line): - return (line == "\n") or (line == "\r") + def is_separator(line): + return (line == separator) + + def is_newline(s): + return (s == "\n") def remove_new_line(line): if (len(line) >= 1) and (is_newline(line[-1])): @@ -76,15 +85,13 @@ def encode_notes(note_lines): cur_notes = "" for line in note_lines: - # remove whitespace at beginning and end - line = line.strip(" ") + line = remove_new_line(line) - if is_newline(line): + if is_separator(line): if cur_notes: note_list.append(cur_notes) cur_notes = "" else: - line = remove_new_line(line) if not is_title(line): cur_notes += line + "\n" # newline @@ -94,7 +101,7 @@ def encode_notes(note_lines): return note_list -def get_notes(file_path): +def get_notes(file_path, separator): """ Takes a path to a file and returns a list with the notes in the file encoded according to the note fromatting. @@ -106,7 +113,7 @@ def get_notes(file_path): if not note_lines: return False - note_list = encode_notes(note_lines) + note_list = decode_notes(note_lines, separator) return note_list diff --git a/setting_handler.py b/setting_handler.py index 8c4442f..7d9cab8 100644 --- a/setting_handler.py +++ b/setting_handler.py @@ -127,6 +127,9 @@ def validate_settings(settings): if not validate_pixels(settings["height"]): return False + if not validate_separator(settings["separator"]): + return False + return True @@ -171,6 +174,12 @@ def edit_settings(root_wnd, apply_method): layout_label = tkinter.Label(settings_wnd, text=config.SETTINGS_OPTIONS["DOUBLE_LAYOUT"], font=config.GUI_FONT) + newline_label = tkinter.Label(settings_wnd, + text=config.SETTINGS_OPTIONS["NEW_LINE_SEPARATOR"], + font=config.GUI_FONT) + separator_label = tkinter.Label(settings_wnd, + text=config.SETTINGS_OPTIONS["CUSTOM_SEPARATOR"], + font=config.GUI_FONT) port_label = tkinter.Label(settings_wnd, text=config.SETTINGS_OPTIONS["SERVER_PORT"], font=config.GUI_FONT) @@ -243,6 +252,28 @@ def edit_settings(root_wnd, apply_method): if decode_boolean_setting(settings["double_layout"]): double_layout_btn.select() + # Separator selection + separator_entry = tkinter.Entry(settings_wnd, width=14, font=config.GUI_FONT) + + def set_separator_active(active): + if active: + separator_entry.configure(state="normal") + else: + separator_entry.configure(state="disabled") + + use_newline = tkinter.BooleanVar() + newline_btn = tkinter.Checkbutton(settings_wnd, + variable=use_newline, + command= + (lambda: set_separator_active(not use_newline.get())) + ) + + if settings["separator"] == config.NEWLINE_CONSTANT: + newline_btn.select() + set_separator_active(False); + else: + separator_entry.insert(0, settings["separator"]) + # Save and cancel buttons def control_and_save(): errors_found = False @@ -252,6 +283,11 @@ def edit_settings(root_wnd, apply_method): chosen_font_size = font_size_entry.get() chosen_port = port_entry.get() + if use_newline.get(): + chosen_separator = config.NEWLINE_CONSTANT + else: + chosen_separator = separator_entry.get() + settings["double_layout"] = encode_boolean_setting(double_layout.get()) if not validate_font_size(chosen_font_size): @@ -266,6 +302,12 @@ def edit_settings(root_wnd, apply_method): else: settings["server_port"] = chosen_port + if not validate_separator(chosen_separator): + msgbox.showerror(config.ERRORS["SEPARATOR"][0], config.ERRORS["SEPARATOR"][1]) + errors_found = True + else: + settings["separator"] = chosen_separator + if not errors_found: save_settings(settings) apply_method(settings) @@ -288,18 +330,22 @@ def edit_settings(root_wnd, apply_method): text_color_label.place(x=15, y=95) bg_color_label.place(x=15, y=135) layout_label.place(x=15, y=175) - port_label.place(x=15, y=215) - default_port_label.place(x=15, y=240) + newline_label.place(x=15, y=215) + separator_label.place(x=15, y=240) + port_label.place(x=15, y=280) + default_port_label.place(x=15, y=305) - 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) - double_layout_btn.place(x=180, y=175) - port_entry.place(x=180, y=215) + font_dropdown.place(x=208, y=15) + font_size_entry.place(x=210, y=55) + text_color.place(x=210, y=95) + bg_color.place(x=210, y=135) + double_layout_btn.place(x=210, y=175) + newline_btn.place(x=210, y=215) + separator_entry.place(x=210, y=240) + port_entry.place(x=210, y=280) - save_btn.place(x=110, y=280) - cancel_btn.place(x=190, y=280) + save_btn.place(x=110, y=350) + cancel_btn.place(x=190, y=350) def validate_color(color): @@ -365,7 +411,7 @@ def encode_boolean_setting(value): def validate_pixels(pixels): """ Checks if given string can be used as a pixel value for height or width. - Height or Width ar assumed to never surpass 10000 + Height or Width or assumed to never surpass 10000 """ try: pixels = int(pixels) @@ -373,3 +419,7 @@ def validate_pixels(pixels): return False return 0 < pixels < 10000 + + +def validate_separator(separator): + return separator.strip()