From fb93daeb466ed6c493cf581d68254514abee62cf Mon Sep 17 00:00:00 2001 From: Ferdi Franceschini Date: Sat, 5 Jul 2014 19:37:23 +1000 Subject: [PATCH] Provide set_imp(opt,imp) method to keep opt and imp mappings in sync. Added convenience method iter_implementations(opt) to enable looping over an option's implementation list. Setting option labels now works properly when switching configurations. --- site_ansto/instrument/util/config_edit.py | 184 ++++++++++++---------- 1 file changed, 100 insertions(+), 84 deletions(-) diff --git a/site_ansto/instrument/util/config_edit.py b/site_ansto/instrument/util/config_edit.py index 2ee99b47..a6b9cea6 100755 --- a/site_ansto/instrument/util/config_edit.py +++ b/site_ansto/instrument/util/config_edit.py @@ -29,7 +29,6 @@ import urwid import copy from collections import defaultdict - Palette = [ ('body', 'dark cyan', '', 'standout'), ('focus', 'dark red', '', 'standout'), @@ -37,12 +36,11 @@ Palette = [ ] -#FIXME Replace the [(name,stateval)] list imp_states with list of item names class RadioButtonListWalker(urwid.SimpleListWalker): - button_dict = {} def __init__(self, item_states, on_state_change=None, user_data=None): radio_grp = [] mapped_rb_list = [] + self.button_dict = {} for item,stateval in item_states: rb = urwid.RadioButton(radio_grp, item, state=stateval, on_state_change=on_state_change, user_data=user_data) self.button_dict[item] = rb @@ -54,9 +52,9 @@ class RadioButtonListWalker(urwid.SimpleListWalker): class CheckBoxListWalker(urwid.SimpleListWalker): - button_dict = {} def __init__(self, item_states, on_state_change = None, user_data = None): mapped_cb_list = [] + self.button_dict = {} for item,stateval in item_states: cb = urwid.CheckBox(item, state = stateval, on_state_change = on_state_change, user_data = user_data) self.button_dict[item] = cb @@ -114,62 +112,28 @@ class ImpListBox(ClosedListBox): return -class InstConfigView(urwid.Pile): - - def __init__(self, cf_dat, cf_man, dbmsg): - self.cf_dat = cf_dat - self.cf_man = cf_man - option_ListBoxes = [ - self.cf_man.config_lb, - self.cf_man.opt_lb, - self.cf_man.imp_lb, - dbmsg] - super(InstConfigView, self).__init__(option_ListBoxes) - return - - def keyinput(self, key): - if key == 'meta q': - raise urwid.ExitMainLoop() - elif key == 'w': - self.cf_dat.backup_files() - self.cf_dat.write_config_file() - elif key in ['right', 'tab']: - if self.get_focus() == self.cf_man.config_lb: - self.set_focus(self.cf_man.opt_lb) - elif self.get_focus() == self.cf_man.opt_lb: - self.set_focus(self.cf_man.imp_lb) - else: - self.set_focus(self.cf_man.config_lb) - elif key in ['left', 'shift tab']: - if self.get_focus() == self.cf_man.config_lb: - self.set_focus(self.cf_man.imp_lb) - elif self.get_focus() == self.cf_man.opt_lb: - self.set_focus(self.cf_man.config_lb) - else: - self.set_focus(self.cf_man.opt_lb) - return - - class InstConfigData: msg_index = 4 # configuration_dict: dict of instrument configurations as defined below, # {configname: {'enabled':T/F, 'cascade_list':[(option, dflt_imp)]} } configuration_dict = defaultdict(dict) - # opt_dict: dict of configuration options as defined below, - # {optname:{'enabled': T/F/Always, 'imptype':optype, 'selected_imp':dflt}} - opt_dict = defaultdict(dict) - # imp_dict: dict of implementations indexed by optype, # {optype: [impname] } imp_dict = defaultdict(list) + # opt_dict: dict of configuration options as defined below, + # {optname:{'enabled': T/F/Always, 'imptype':optype, 'selected_imp':dflt}} + opt_dict = defaultdict(dict) + # imp2opt_dict: Maps each implementation to an option or None, # {imp: opt/None} imp2opt_dict = {} - def __init__(self): - return + # optypelist: list of (opt, optype) tuples + # [(opt, optype)] + optypelist = [] + def __get_configurations(self): for s in self.file_parser.sections(): @@ -187,6 +151,14 @@ class InstConfigData: self.configuration_dict[s]['cascade_list'] = cascade_list def __get_options(self): + # opt_dict: dict of configuration options as defined below, + # {optname:{'enabled': T/F/Always, 'imptype':optype, 'selected_imp':dflt}} + opt_dict = defaultdict(dict) + + # imp2opt_dict: Maps each implementation to an option or None, + # {imp: opt/None} + imp2opt_dict = {} + for s in self.file_parser.sections(): if self.file_parser.has_option(s, 'implementation'): selected_imp = self.file_parser.get(s, 'implementation') @@ -229,6 +201,19 @@ class InstConfigData: print 'Add imp2opt_dict[{0}] = none'.format(s) self.imp2opt_dict[s] = 'none' + def set_imp(self, opt, new_imp): + old_imp =self.opt_dict[opt]['selected_imp'] + self.imp2opt_dict[old_imp] = 'none' + self.opt_dict[opt]['selected_imp'] = new_imp + self.imp2opt_dict[new_imp] = opt + + def get_optypelist (self): + return self.optypelist + + def iter_implementations(self, opt): + dict = self.opt_dict[opt] + for imp in self.imp_dict[dict['imptype']]: + yield imp def read_config_file(self, config_filename): self.config_filename = config_filename @@ -237,6 +222,9 @@ class InstConfigData: self.__get_options() self.__get_implementations() self.__get_configurations() + for opt,dict in self.opt_dict.iteritems(): + self.optypelist.append((opt, dict['imptype'])) + return def backup_files(self): @@ -279,11 +267,7 @@ class InstConfigData: self.configuration_dict[cfg_id]['enabled'] = new_state def opt_statechange(self, checkbox, new_state, udat=None): - if SET_LABEL: - opt = checkbox.get_label().split(':')[0] - else: - opt = checkbox.get_label() - + opt = checkbox.get_label().split(':')[0] dbg.msg(3, 'InstConfigData:opt_statechange({0},{1},{2})'.format(opt, new_state, udat)) self.opt_dict[opt]['enabled'] = new_state @@ -295,6 +279,42 @@ class InstConfigData: self.opt_dict[opt]['selected_imp'] = selected_imp +class InstConfigView(urwid.Pile): + + def __init__(self, cf_dat, cf_man, dbmsg): + self.cf_dat = cf_dat + self.cf_man = cf_man + option_ListBoxes = [ + self.cf_man.config_lb, + self.cf_man.opt_lb, + self.cf_man.imp_lb, + dbmsg] + super(InstConfigView, self).__init__(option_ListBoxes) + return + + def keyinput(self, key): + if key == 'meta q': + raise urwid.ExitMainLoop() + elif key == 'w': + self.cf_dat.backup_files() + self.cf_dat.write_config_file() + elif key in ['right', 'tab']: + if self.get_focus() == self.cf_man.config_lb: + self.set_focus(self.cf_man.opt_lb) + elif self.get_focus() == self.cf_man.opt_lb: + self.set_focus(self.cf_man.imp_lb) + else: + self.set_focus(self.cf_man.config_lb) + elif key in ['left', 'shift tab']: + if self.get_focus() == self.cf_man.config_lb: + self.set_focus(self.cf_man.imp_lb) + elif self.get_focus() == self.cf_man.opt_lb: + self.set_focus(self.cf_man.config_lb) + else: + self.set_focus(self.cf_man.opt_lb) + return + + # Contains OptionListWalker dict indexed by option # Contains ImpListBox # Connects OptionListWalker 'focus_change' signal to update_imp_lb handler @@ -302,29 +322,26 @@ class InstConfigData: # and sets selection on ImpListBox class InstConfigManager: cf_msg_index = 8 - options = [] imp_lw_dict = {} def __init__(self, cf_dat): self.cf_dat = cf_dat urwid.register_signal(InstConfigManager, ['focus_change']) - for opt,dict in cf_dat.opt_dict.iteritems(): - self.options.append((opt, dict['imptype'])) + self.options = self.cf_dat.get_optypelist() self.options.sort() firstopt = self.options[0][0] self.imp_lw = self.__gen_imp_listwalker(firstopt) - self.option_lw = OptionListWalker(cf_dat.opt_dict, self.opt_statechange) - if (SET_LABEL): - for label, button in self.option_lw.button_dict.iteritems(): - button.set_label('{0}:{1}'.format(label, self.cf_dat.opt_dict[label]['selected_imp'])) + self.opt_lw = OptionListWalker(cf_dat.opt_dict, self.opt_statechange) + for label, button in self.opt_lw.button_dict.iteritems(): + button.set_label('{0}:{1}'.format(label, self.cf_dat.opt_dict[label]['selected_imp'])) self.imp_lb = ImpListBox(self.imp_lw) - urwid.connect_signal(self.option_lw, 'focus_change', self.update_imp_lb) + urwid.connect_signal(self.opt_lw, 'focus_change', self.update_imp_lb) item_states = [(i,d['enabled']) for i,d in cf_dat.configuration_dict.iteritems()] item_states.sort() self.cfg_lw = RadioButtonListWalker(item_states, on_state_change = self.cf_statechange) self.config_lb = OptionListBox(self.cfg_lw) - self.opt_lb = OptionListBox(self.option_lw) + self.opt_lb = OptionListBox(self.opt_lw) self.opt_lb.set_focus(0) return @@ -342,11 +359,10 @@ class InstConfigManager: def __gen_imp_listwalker(self, opt): imp_items = [] - dict = self.cf_dat.opt_dict[opt] - for imp in self.cf_dat.imp_dict[dict['imptype']]: + for imp in self.cf_dat.iter_implementations(opt): if self.__imp_unavailable(imp): continue - if imp == dict['selected_imp']: + if imp == self.cf_dat.opt_dict[opt]['selected_imp']: imp_items.append((imp, True)) else: imp_items.append((imp, False)) @@ -359,39 +375,40 @@ class InstConfigManager: self.cf_dat.cf_statechange(button, new_state, udat) b = button.get_label() cascade = self.cf_dat.configuration_dict[b]['cascade_list'] + if new_state == True: for opt in self.cf_dat.opt_dict.keys(): +# self.cf_dat.set_imp(opt, 'none') + self.opt_lw.button_dict[opt].set_state(False) if self.cf_dat.opt_dict[opt]['permanent'] == False: - self.option_lw.button_dict[opt].set_state(False) + self.opt_lw.button_dict[opt].set_state(False) for opt,imp in cascade: - self.option_lw.button_dict[opt].set_state(True) + self.cf_dat.set_imp(opt, imp) + self.opt_lw.button_dict[opt].set_state(True) imp_lw = self.__gen_imp_listwalker(opt) - imp_lw.button_dict[imp].set_state(True) - currpos = self.opt_lb.get_focus()[1] - self.opt_lb.set_focus(currpos) +# imp_lw.button_dict[imp].set_state(True) + +# currpos = self.opt_lb.get_focus()[1] +# self.opt_lb.set_focus(currpos) dbg.msg(self.cf_msg_index, 'InstConfigManager:cf_statechange({0},{1},{2}), cascade = {3}'.format(b, new_state, udat, cascade)) self.cf_msg_index = (self.cf_msg_index - 7) % 2 + 8 return def opt_statechange(self, button, new_state, udat=None): - if (SET_LABEL): - opt = button.get_label().split(':')[0] - else: - opt = button.get_label() - + opt = button.get_label().split(':')[0] imp = self.cf_dat.opt_dict[opt]['selected_imp'] if new_state == True: if self.__imp_unavailable(imp): self.cf_dat.opt_dict[opt]['selected_imp'] = 'none' imp_button = self.imp_lw.button_dict['none'] imp_button.set_state(True) - if SET_LABEL: - opt_button = self.option_lw.button_dict[opt] - opt_button.set_label('{0}:none'.format(opt)) -# FORCE DEDENT a blank line isn't enough in vim + opt_button = self.opt_lw.button_dict[opt] + opt_button.set_label('{0}:none'.format(opt)) else: - self.cf_dat.imp2opt_dict[imp] = opt + opt_button = self.opt_lw.button_dict[opt] + opt_button.set_label('{0}:{1}'.format(opt,imp)) + self.cf_dat.set_imp(opt, imp) self.cf_dat.opt_statechange(button, new_state, udat) return @@ -399,10 +416,9 @@ class InstConfigManager: def imp_statechange(self, button, new_state, opt): if new_state == True: imp = button.get_label() - self.cf_dat.imp2opt_dict[imp] = opt - if SET_LABEL: - opt_button = self.option_lw.button_dict[opt] - opt_button.set_label('{0}:{1}'.format(opt, imp)) + self.cf_dat.set_imp(opt, imp) + opt_button = self.opt_lw.button_dict[opt] + opt_button.set_label('{0}:{1}'.format(opt, imp)) self.cf_dat.imp_statechange(button, new_state, opt) return @@ -443,8 +459,8 @@ class DEBUG: dbg = DEBUG(enabled=True) def main(config_ini): - global cf_dat, cf_man, cf_viewer, SET_LABEL - SET_LABEL = True + global cf_dat, cf_man, cf_viewer + # Make configuration data cf_dat = InstConfigData() cf_dat.read_config_file(config_ini)