#!/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 = [] 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.AttrWrap(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.AttrWrap(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.AttrWrap(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.AttrWrap(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 += ")" cb = urwid.AttrWrap(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.AttrWrap(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.AttrWrap(urwid.Text(text_header), 'header') sflw = urwid.SimpleListWalker(lb_list) listbox = urwid.ListBox(sflw) frame = urwid.Frame(urwid.AttrWrap(listbox, 'body'), header=header) frame.footer = urwid.AttrWrap(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.AttrWrap(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.AttrWrap(urwid.Edit(edit_text=u"Hello"), 'header')) # l.set_focus(b + 1) # frame.footer = urwid.AttrWrap(urwid.Text([u"EditB: " + str(b)]), 'header') else: if not key[0] == 'mouse release': frame.footer = urwid.AttrWrap(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)