Files
SplitNotes/setting_handler.py
T
Joelnir af125173c4 Settings Menu
Finished the settings menu and systems for saving and loading settings
from a config file.
2016-02-18 16:28:54 +01:00

317 lines
7.9 KiB
Python

import tkinter.colorchooser as colorchooser
from tkinter import messagebox as msgbox
import tkinter
import os
import sys
import config
settings_path = os.path.join(
str(os.path.dirname(os.path.realpath(sys.argv[0]))),
config.RESOURCE_FOLDER,
config.SETTINGS_FILE
)
settings_icon_path = os.path.join(
str(os.path.dirname(os.path.realpath(sys.argv[0]))),
config.RESOURCE_FOLDER,
config.ICONS["SETTINGS"]
)
def load_settings():
"""
Tries to load settings from file.
If no working settings-file exist one is created and the default settings are returned.
returns a dictionary with all settings.
"""
# try to open default settings file
try:
settings_file = open(settings_path, "r+")
settings_content = get_file_lines(settings_file)
except:
# File not found
settings_content = set_default_settings();
settings = format_settings(settings_content)
# Check so settings file has all settings
if not validate_settings(settings):
settings = format_settings(set_default_settings())
return settings
def set_default_settings():
"""
Creates a config file with default settings.
Returns the default config-file content.
"""
set_settings_file_content(config.DEFAULT_CONFIG)
return config.DEFAULT_CONFIG.split("\n")
def format_settings(file_rows):
"""
Takes a list of settings (as written in config files) and
formats it to a dictionary.
Returns a dictionary with all settings as keys.
"""
SETTING_PART_LENGTH = 2
settings = {}
for row in file_rows:
row = row.strip("\n")
parts = row.split("=")
if len(parts) == SETTING_PART_LENGTH:
settings[parts[0]] = parts[1]
return settings
def get_file_lines(file):
"""
Returns a list containing all the lines of the gicen file.
"""
# read file line per line
f_lines = []
keep_reading = True
while keep_reading:
cur_line = file.readline()
if cur_line:
f_lines.append(cur_line)
else:
keep_reading = False
return f_lines
def validate_settings(settings):
"""
Checks a settings dictionary so that all the needed settings are present.
"""
for req_setting in config.REQUIRED_SETTINGS:
if not (req_setting in settings):
return False
if not validate_font_size(settings["font_size"]):
return False
if not validate_server_port(settings["server_port"]):
return False
if not validate_color(settings["text_color"]):
return False
if not validate_color(settings["background_color"]):
return False
if not (settings["font"] in config.AVAILABLE_FONTS):
return False
return True
def set_settings_file_content(content):
"""
Saves given content to the config file, config.cfg, in the resources directory.
"""
settings_file = open(settings_path, "w")
settings_file.write(content)
settings_file.close()
def edit_settings(root_wnd, apply_method):
"""
Sets up a window for editing settings.
root_wnd is the main window that settings should be applied to.
apply_method is the method to be called to apply validated settings.
"""
settings_wnd = tkinter.Toplevel(master=root_wnd,
width=config.SETTINGS_WINDOW["WIDTH"],
height=config.SETTINGS_WINDOW["HEIGHT"])
settings_wnd.title(config.SETTINGS_WINDOW["TITLE"])
settings_icon = tkinter.Image("photo", file=settings_icon_path)
settings_wnd.tk.call('wm', 'iconphoto', settings_wnd._w, settings_icon)
settings = load_settings()
settings_wnd.resizable(0, 0)
font_label = tkinter.Label(settings_wnd,
text=config.SETTINGS_OPTIONS["FONT"],
font=config.GUI_FONT)
font_size_label = tkinter.Label(settings_wnd,
text=config.SETTINGS_OPTIONS["FONT_SIZE"],
font=config.GUI_FONT)
text_color_label = tkinter.Label(settings_wnd,
text=config.SETTINGS_OPTIONS["TEXT_COLOR"],
font=config.GUI_FONT)
bg_color_label = tkinter.Label(settings_wnd,
text=config.SETTINGS_OPTIONS["BG_COLOR"],
font=config.GUI_FONT)
port_label = tkinter.Label(settings_wnd,
text=config.SETTINGS_OPTIONS["SERVER_PORT"],
font=config.GUI_FONT)
default_port_label = tkinter.Label(settings_wnd,
text=config.SETTINGS_OPTIONS["DEFAULT_SERVER_PORT"],
font=config.GUI_FONT)
# Font Selection
selected_font = tkinter.StringVar(settings_wnd)
selected_font.set(settings["font"])
font_dropdown = tkinter.OptionMenu(settings_wnd,
selected_font,
*config.AVAILABLE_FONTS)
font_dropdown.configure(font=config.GUI_FONT)
# Font Size Selection
font_size_entry = tkinter.Entry(settings_wnd, width=2, font=config.GUI_FONT)
font_size_entry.insert(0, settings["font_size"])
# Text Color Selection
text_color = tkinter.Button(settings_wnd,
width=3,
height=1,
)
if validate_color(settings["text_color"]):
text_color.configure(background=settings["text_color"])
else:
text_color.configure(background="#000000")
def text_color_selection():
choosen_color = colorchooser.askcolor()
if choosen_color[1]:
settings["text_color"] = choosen_color[1]
text_color.configure(background=settings["text_color"])
settings_wnd.focus_force()
text_color.configure(command=text_color_selection)
# Background color Selection
bg_color = tkinter.Button(settings_wnd,
width=3,
height=1,
)
if validate_color(settings["background_color"]):
bg_color.configure(background=settings["background_color"])
else:
bg_color.configure(background="#FFFFFF")
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"])
settings_wnd.focus_force()
bg_color.configure(command=bg_color_selection)
# Server port Selection
port_entry = tkinter.Entry(settings_wnd, width=6, font=config.GUI_FONT)
port_entry.insert(0, settings["server_port"])
# Save and cancel buttons
def control_and_save():
errors_found = False
settings["font"] = selected_font.get()
chosen_font_size = font_size_entry.get()
chosen_port = port_entry.get()
if not validate_font_size(chosen_font_size):
msgbox.showerror(config.ERRORS["FONT_SIZE"][0], config.ERRORS["FONT_SIZE"][1])
errors_found = True
else:
settings["font_size"] = chosen_font_size
if not validate_server_port(chosen_port):
msgbox.showerror(config.ERRORS["SERVER_PORT"][0], config.ERRORS["SERVER_PORT"][1])
errors_found = True
else:
settings["server_port"] = chosen_port
if not errors_found:
save_settings(settings)
apply_method(settings)
settings_wnd.destroy()
else:
settings_wnd.focus_force()
save_btn = tkinter.Button(settings_wnd,
command=control_and_save,
text=config.SETTINGS_WINDOW["SAVE"],
font=config.GUI_FONT)
cancel_btn = tkinter.Button(settings_wnd,
command=settings_wnd.destroy,
text=config.SETTINGS_WINDOW["CANCEL"],
font=config.GUI_FONT)
# Place all components
font_label.place(x=15, y=15)
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)
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)
save_btn.place(x=110, y=230)
cancel_btn.place(x=190, y=230)
def validate_color(color):
"""
Returns whether or not given color is valid in the hexadecimal format.
"""
return isinstance(color, str) and len(color) == 7 and color[0] == "#"
def validate_font_size(size):
"""
Returns whether or not given size is an acceptable font size.
"""
try:
size = int(size)
except:
return False
return 0 < size < 70
def validate_server_port(port):
"""
Returns Whether or not gicen port is a valid server port.
"""
try:
port = int(port)
return True
except:
return False
def save_settings(settings):
file_content = ""
for key in settings.keys():
file_content += key + "=" + settings[key] + "\n"
set_settings_file_content(file_content)