237 lines
8.2 KiB
Python
Executable File
237 lines
8.2 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# vim: tabstop=8 softtabstop=2 shiftwidth=2 nocin si et ft=python
|
|
|
|
import os
|
|
import sys
|
|
|
|
global config
|
|
global verbose
|
|
global depth_list, line_list
|
|
config = None
|
|
verbose = False
|
|
depth_list = []
|
|
line_list = []
|
|
Radio_Groups = {}
|
|
|
|
def read_config_file(config_filename):
|
|
import ConfigParser
|
|
config = ConfigParser.SafeConfigParser()
|
|
config.read(config_filename)
|
|
return config
|
|
|
|
def reread_config_file(config_filename, cb_list):
|
|
config = read_config_file(config_filename)
|
|
for cb in cb_list:
|
|
lbl = cb.get_label()
|
|
if ":" in lbl:
|
|
lbl = lbl.split(":")[0]
|
|
state = False
|
|
if 'enabled' in config.options(lbl):
|
|
if config.get(lbl, 'enabled').lower() in ['1', 'yes', 'true']:
|
|
state = True
|
|
config.set(lbl, 'enabled', str(state))
|
|
cb.set_state(state, False)
|
|
return config
|
|
|
|
def write_config_file(config, config_filename):
|
|
for idx in range(8, 0, -1):
|
|
if os.path.exists(config_filename + "." + str(idx)):
|
|
os.rename(config_filename + "." + str(idx),
|
|
config_filename + "." + str(idx + 1))
|
|
if os.path.exists(config_filename):
|
|
os.rename(config_filename, config_filename + ".1")
|
|
with open(config_filename, "wb") as configfile:
|
|
for section in sorted(config.sections()):
|
|
configfile.write("[%s]\n" % section)
|
|
for option in sorted(config.options(section)):
|
|
configfile.write("%s = %s\n" % (option, config.get(section, option)))
|
|
configfile.write("\n")
|
|
#config.write(configfile)
|
|
|
|
def do_cascade(config, name, cb_list, label, new_state):
|
|
global depth_list
|
|
try:
|
|
if name in depth_list:
|
|
depth_list.append(name)
|
|
raise Exception("Recursion on " + str(depth_list))
|
|
depth_list.append(name)
|
|
if label in config.options(name):
|
|
cascade_list = config.get(name, label).lower().split(",")
|
|
for cb in cb_list:
|
|
lbl = cb.get_label().lower()
|
|
if ":" in lbl:
|
|
lbl = lbl.split(":")[0]
|
|
if lbl in cascade_list:
|
|
cb.set_state(new_state)
|
|
finally:
|
|
depth_list.pop()
|
|
|
|
def main(config_filename):
|
|
import urwid
|
|
global config
|
|
|
|
config = read_config_file(config_filename)
|
|
text_header = (
|
|
u"SICS Config Editor! SPACE/ENTER: Toggle, w/W/F12: Write+Exit\n"
|
|
u"UP/DOWN/PAGE UP/PAGE DOWN: scroll, r/R: Reread, q/Q/F8: Quit")
|
|
|
|
def checkbox_change(check_box, new_state, user_data):
|
|
global config, verbose, depth_list, line_list
|
|
if len(depth_list) == 0:
|
|
line_list = []
|
|
frame.footer = urwid.AttrMap(urwid.Text(""), 'header')
|
|
config.set(user_data, 'enabled', str(new_state))
|
|
if verbose:
|
|
line = u"Checkbox: name=%s, new_state=%s, user_data=%s" % (
|
|
check_box.get_label(), str(new_state), str(user_data))
|
|
line_list.append(line + "\n")
|
|
frame.footer = urwid.AttrMap(urwid.Text(line_list), 'header')
|
|
try:
|
|
order = ['offifoff', 'offifon', 'onifon', 'onifoff', 'cascade']
|
|
if 'order' in config.options(user_data):
|
|
order = config.get(user_data, 'order').lower().split(",")
|
|
for item in order:
|
|
if 'cascade' == item:
|
|
do_cascade(config, user_data, cb_list, 'cascade', new_state)
|
|
if (True == new_state) and 'onifon' == item:
|
|
do_cascade(config, user_data, cb_list, 'onifon', True)
|
|
if (True == new_state) and 'offifon' == item:
|
|
do_cascade(config, user_data, cb_list, 'offifon', False)
|
|
if (False == new_state) and 'onifoff' == item:
|
|
do_cascade(config, user_data, cb_list, 'onifoff', True)
|
|
if (False == new_state) and 'offifoff' == item:
|
|
do_cascade(config, user_data, cb_list, 'offifoff', False)
|
|
except Exception as prang:
|
|
line = "Exception: %s" % prang
|
|
line_list.append(line + "\n")
|
|
frame.footer = urwid.AttrMap(urwid.Text(line_list), 'header')
|
|
|
|
text_cb_list = list(config.sections())
|
|
cb_map = {}
|
|
for txt in sorted(text_cb_list):
|
|
if 'group' in config.options(txt):
|
|
group = config.get(txt, 'group').lower()
|
|
else:
|
|
group = ""
|
|
if group not in cb_map:
|
|
cb_map[group] = []
|
|
cb_map[group].append(txt)
|
|
lb_list = []
|
|
cb_list = []
|
|
for key in sorted(cb_map.keys()):
|
|
if len(key) > 0:
|
|
lb_list.append(urwid.AttrMap(urwid.Text("Group: %s" % key), 'bright'))
|
|
for txt in sorted(cb_map[key]):
|
|
state = False
|
|
if 'enabled' in config.options(txt):
|
|
if config.get(txt, 'enabled').lower() in ['1', 'yes', 'true']:
|
|
state = True
|
|
config.set(txt, 'enabled', str(state))
|
|
cb_text = txt
|
|
if 'group' in config.options(txt) or 'desc' in config.options(txt):
|
|
cb_text += ": ("
|
|
if 'group' in config.options(txt):
|
|
cb_text += config.get(txt, 'group').strip("\"") + ": "
|
|
if 'desc' in config.options(txt):
|
|
cb_text += config.get(txt, 'desc').strip("\"")
|
|
cb_text += ")"
|
|
if 'radio' in config.options(txt):
|
|
radio = config.get(txt, 'radio').strip("\"")
|
|
if radio not in Radio_Groups:
|
|
Radio_Groups[radio] = []
|
|
cb = urwid.AttrMap(urwid.RadioButton(
|
|
Radio_Groups[radio],
|
|
cb_text,
|
|
state=state,
|
|
on_state_change=checkbox_change,
|
|
user_data=txt), 'buttn', 'buttnf')
|
|
else:
|
|
cb = urwid.AttrMap(urwid.CheckBox(cb_text,
|
|
state=state,
|
|
on_state_change=checkbox_change,
|
|
user_data=txt), 'buttn', 'buttnf')
|
|
cb_list.append(cb)
|
|
lb_list.append(cb)
|
|
|
|
def fcc(focus):
|
|
frame.footer = urwid.AttrMap(urwid.Text(
|
|
[u"Focus: " + str(focus)]), 'header')
|
|
|
|
|
|
blank = urwid.Divider()
|
|
listbox_content = [
|
|
blank,
|
|
urwid.Padding(urwid.GridFlow(
|
|
cb_list,
|
|
76, 1, 0, 'left'),
|
|
left=2, right=2, min_width=76),
|
|
blank,
|
|
blank
|
|
]
|
|
|
|
|
|
header = urwid.AttrMap(urwid.Text(text_header), 'header')
|
|
sflw = urwid.SimpleListWalker(lb_list)
|
|
listbox = urwid.ListBox(sflw)
|
|
frame = urwid.Frame(urwid.AttrMap(listbox, 'body'), header=header)
|
|
frame.footer = urwid.AttrMap(urwid.Text(""), 'header')
|
|
|
|
palette = [
|
|
('body', 'black', 'light gray', 'standout'),
|
|
('reverse', 'light gray', 'black'),
|
|
('header', 'white', 'dark red', 'bold'),
|
|
('important', 'dark blue', 'light gray', ('standout', 'underline')),
|
|
('editfc', 'white', 'dark blue', 'bold'),
|
|
('editbx', 'light gray', 'dark blue'),
|
|
('editcp', 'black', 'light gray', 'standout'),
|
|
('bright', 'dark gray', 'light gray', ('bold', 'standout')),
|
|
('buttn', 'black', 'dark cyan'),
|
|
('buttnf', 'white', 'dark blue', 'bold'),
|
|
]
|
|
|
|
def unhandled(key):
|
|
global config
|
|
if key in ['w', 'W', 'f12']:
|
|
write_config_file(config, config_filename)
|
|
raise urwid.ExitMainLoop()
|
|
elif key in ['r', 'R']:
|
|
config = reread_config_file(config_filename, cb_list)
|
|
elif key in ['e', 'E', 'f4']:
|
|
f = sflw.get_focus()
|
|
frame.footer = urwid.AttrMap(urwid.Text([u"EditE: " + str(dir(f[0]))]), 'header')
|
|
elif key in ['q', 'Q', 'f8']:
|
|
raise urwid.ExitMainLoop()
|
|
# elif key in ['b', 'B']:
|
|
# l = sflw[1].base_widget
|
|
# f = l.focus_cell
|
|
# b = l.cells.index(f)
|
|
# l.cells.insert(b + 1, urwid.AttrMap(urwid.Edit(edit_text=u"Hello"), 'header'))
|
|
# l.set_focus(b + 1)
|
|
# frame.footer = urwid.AttrMap(urwid.Text([u"EditB: " + str(b)]), 'header')
|
|
else:
|
|
if not key[0] == 'mouse release':
|
|
frame.footer = urwid.AttrMap(urwid.Text([u"Press: " + str(key)]), 'header')
|
|
|
|
urwid.MainLoop(frame, palette, unhandled_input=unhandled).run()
|
|
|
|
|
|
if '__main__'==__name__:
|
|
global verbose
|
|
import argparse
|
|
|
|
# set default_ini to the name of the file to edit when no name is supplied
|
|
default_ini = "/usr/local/sics/sics_config.ini"
|
|
parser = argparse.ArgumentParser(description = """
|
|
Edit a configuration (*.ini) file using python urwid widget library.
|
|
Options can be enabled or disabled with mouse or spacebar.
|
|
The default configuration filename is %s.
|
|
""" % default_ini)
|
|
parser.add_argument("-v", "--verbose", action="store_true", help="give more infor in the footer")
|
|
parser.add_argument("path", nargs="?", default = default_ini, help="name of file to edit [%s]" % default_ini)
|
|
args = parser.parse_args()
|
|
default_ini = os.path.abspath(args.path)
|
|
if args.verbose:
|
|
verbose = True
|
|
main(default_ini)
|
|
|