def create_select_checkbox(screen, title, text, items, buttons=(('Cancel', 'cancel', 'F12'), 'Ok'), width=40, scroll=0, height=-1, help=None): """Helper class for displaying a windows with a checkbox list. On exit, list of selected items is returned""" if (height == -1): height = len(items) if len(items) > height: scroll = 1 bb = ButtonBar(screen, buttons) t = TextboxReflowed(width, text) cb = CheckboxTree(height, scroll=scroll) count = 0 for count, item in enumerate(items): if isinstance(item, types.TupleType): (text, key, selected) = item else: text = item key = count selected = 0 cb.append(text, key, selected) g = GridFormHelp(screen, title, help, 1, 3) g.add(t, 0, 0) g.add(cb, 0, 1, padding=(0, 1, 0, 1)) g.add(bb, 0, 2, growx=1) rc = g.runOnce() return (bb.buttonPressed(rc), cb.getSelection())
def create_select_checkbox(screen, title, text, items, buttons=('Ok', 'Cancel'), width=40, scroll=0, height=-1, help=None): """Helper class for displaying a windows with a checkbox list. On exit, list of selected items is returned""" if (height == -1): height = len(items) if len(items) > height: scroll = 1 bb = ButtonBar(screen, buttons) t = TextboxReflowed(width, text) cb = CheckboxTree(height, scroll = scroll) count = 0 for count, item in enumerate(items): if isinstance(item, types.TupleType): (text, key, selected) = item else: text = item key = count selected = 0 cb.append(text, key, selected) g = GridFormHelp(screen, title, help, 1, 3) g.add(t, 0, 0) g.add(cb, 0, 1, padding = (0, 1, 0, 1)) g.add(bb, 0, 2, growx = 1) rc = g.runOnce() return (bb.buttonPressed(rc), cb.getSelection())
def display_info(screen, title, info_text="Close me, please.", width=50, height=2): """Display information message on information screen""" g = GridFormHelp(screen, title, help, 1, 2) g.add(Textbox(width, height, info_text, 0, 0), 0, 0, padding=(0, 1, 0, 1)) g.add(Button("OK"), 0, 1) g.runOnce()
def AssistantWindow(screen, title, info, width=40, buttons=["Next", "Previous", "Return"], help=None): from snack import ButtonBar, TextboxReflowed, GridFormHelp, Label """ EntryWindow(): """ bb = ButtonBar(screen, buttons) rb = AssistantInfoRadioBar(screen, info) t = TextboxReflowed(width, info.getComment()) g = GridFormHelp(screen, title, help, 1, 4) g.add(Label(info.getName()), 0, 0, padding=(0, 0, 1, 0), anchorLeft=0) g.add(t, 0, 1, padding=(0, 0, 0, 1)) g.add(bb, 0, 3, growx=1) g.add(rb, 0, 2, padding=(0, 0, 0, 1)) result = g.runOnce() return (bb.buttonPressed(result), rb.getSelection())
def MessageWindow(screen, title, text, width=40, help=None, timer_ms=None, run_type=RT_EXECUTEANDPOP): """ Render a panel with a message and no buttons. This is intended to proceed to the next panel, where some action is taken before returning -its- expression. Meanwhile, this panel is left displayed. Obviously, this panel's timer shouldn't be large, if not zero. """ g = GridFormHelp(screen, title, help, 1, 3) t = TextboxReflowed(width, text) g.add(t, 0, 0) if timer_ms: g.form.w.settimer(timer_ms) (button, is_esc) = ActivateWindow(g, run_type) return {'is_esc': is_esc, 'grid': g, }
def ExtButtonChoiceWindow(screen, title, text, buttons=['Ok', 'Cancel'], width=40, x=None, y=None, help=None): bb = ButtonBar(screen, buttons, compact=1) t = TextboxReflowed(width, text, maxHeight=screen.height - 12) g = GridFormHelp(screen, title, help, 1, 2) g.add(t, 0, 0, padding=(0, 0, 0, 1)) g.add(bb, 0, 1, growx=1) return bb.buttonPressed(g.runOnce(x, y))
def display_yesno(screen, title, question_text="Yes / No", width=50, height=2): """Display yes/no dialog. Return True on yes and False on no.""" g = GridFormHelp(screen, title, help, 1, 2) bb = ButtonBar(screen, (('No', 'no', 'F12'), 'Yes')) g.add(Textbox(width, height, question_text, 0, 0), 0, 0, padding=(0, 1, 0, 1)) g.add(bb, 0, 1) rc = g.runOnce() return bb.buttonPressed(rc) == 'yes'
def ExtEntryWindow(screen, title, text, prompts, allowCancel=1, width=40, entryWidth=20, buttons=['Ok', 'Cancel'], help=None): bb = ButtonBar(screen, buttons, compact=1) t = TextboxReflowed(width, text) count = 0 for n in prompts: count = count + 1 sg = Grid(2, count) count = 0 entryList = [] for n in prompts: if isinstance(n, types.TupleType): (n, e) = n if (type(e) in types.StringTypes): e = Entry(entryWidth, e) else: e = Entry(entryWidth) sg.setField(Label(n), 0, count, padding=(0, 0, 1, 0), anchorLeft=1) sg.setField(e, 1, count, anchorLeft=1) count = count + 1 entryList.append(e) g = GridFormHelp(screen, title, help, 1, 3) g.add(t, 0, 0, padding=(0, 0, 0, 1)) g.add(sg, 0, 1, padding=(0, 0, 0, 1)) g.add(bb, 0, 2, growx=1) result = g.runOnce() entryValues = [] count = 0 for n in prompts: entryValues.append(entryList[count].value()) count = count + 1 return (result, bb.buttonPressed(result), tuple(entryValues))
def ExtListboxChoiceWindow(screen, title, text, items, buttons=('Ok', 'Cancel'), width=40, scroll=0, height=-1, default=None, help=None): if (height == -1): height = len(items) bb = ButtonBar(screen, buttons, compact=1) t = TextboxReflowed(width, text) lb = Listbox(height, scroll=scroll, returnExit=1) count = 0 for item in items: if isinstance(item, types.TupleType): (text, key) = item else: text = item key = count if (default == count): default = key elif (default == item): default = key lb.append(text, key) count = count + 1 if (default is not None): lb.setCurrent(default) g = GridFormHelp(screen, title, help, 1, 3) g.add(t, 0, 0) g.add(lb, 0, 1, padding=(0, 1, 0, 1)) g.add(bb, 0, 2, growx=1) rc = g.runOnce() return (rc, bb.buttonPressed(rc), lb.current())
def ConfirmationWindow(screen, title, infolist, width=40, buttons=["Start", "Modify", "Save", "Exit"], help=None): from snack import ButtonBar, Label, GridFormHelp, Textbox bb = ButtonBar(screen, buttons) ig = Grid(2, len(infolist)) i = 0 for _info in infolist: ig.setField(Label("%s: " % _info.getName()), 0, i, padding=(0, 0, 1, 0), anchorLeft=1) ig.setField(Label("%s" % _info.getValue()), 1, i, padding=(0, 0, 1, 0), anchorLeft=1) i = i + 1 g = GridFormHelp(screen, title, help, 1, 3) g.add(Textbox(20, 1, "Current settings:"), 0, 0, padding=(0, 0, 0, 1), anchorLeft=1) g.add(ig, 0, 1, padding=(0, 0, 0, 1)) g.add(bb, 0, 2, growx=1) result = g.runOnce() return bb.buttonPressed(result)
def ConfirmationWindow(screen, title, infolist, width=40, buttons=['Start', 'Modify', 'Save', 'Exit'], help=None): from snack import ButtonBar, Label, GridFormHelp, Textbox bb = ButtonBar(screen, buttons) ig = Grid(2, len(infolist)) i = 0 for _info in infolist: ig.setField(Label("%s: " % _info.getName()), 0, i, padding=(0, 0, 1, 0), anchorLeft=1) ig.setField(Label("%s" % _info.getValue()), 1, i, padding=(0, 0, 1, 0), anchorLeft=1) i = i + 1 g = GridFormHelp(screen, title, help, 1, 3) g.add(Textbox(20, 1, "Current settings:"), 0, 0, padding=(0, 0, 0, 1), anchorLeft=1) g.add(ig, 0, 1, padding=(0, 0, 0, 1)) g.add(bb, 0, 2, growx=1) result = g.runOnce() return (bb.buttonPressed(result))
def ButtonWindow(screen, title, text, allowCancel = 1, width = 40, entryWidth = 20, buttons = [ 'Ok', 'Cancel' ], help = None): """ EntryWindow(screen, title, text, prompts, allowCancel = 1, width = 40, entryWidth = 20, buttons = [ 'Ok', 'Cancel' ], help = None): """ from snack import ButtonBar, TextboxReflowed, GridFormHelp bb = ButtonBar(screen, buttons); t = TextboxReflowed(width, text) g = GridFormHelp(screen, title, help, 1, 3) g.add(t, 0, 0, padding = (0, 0, 0, 1)) g.add(bb, 0, 1, growx = 1) result = g.runOnce() return [bb.buttonPressed(result)]
def ButtonChoiceWindow(screen, title, text, buttons=['Ok', 'Cancel'], width=40, x=None, y=None, help=None, timer_ms=None, secondary_message=None, secondary_message_width=None, run_type=RT_EXECUTEANDPOP): # Dustin: Added timer_ms parameter. Added secondary_message arguments. # Added result boolean for whether ESC was pressed. Results are now # dictionaries. Added auto_pop parameter. bb = ButtonBar(screen, buttons) t = TextboxReflowed(width, text, maxHeight = screen.height - 12) g = GridFormHelp(screen, title, help, 1, 2 + (1 if secondary_message else 0)) row = 0 g.add(t, 0, row, padding = (0, 0, 0, 1)) row += 1 if secondary_message: if not secondary_message_width: secondary_message_width = width t2 = TextboxReflowed(secondary_message_width, secondary_message) g.add(t2, 0, row, padding = (0, 0, 0, 1)) row += 1 g.add(bb, 0, row, growx = 1) row += 1 if timer_ms: g.form.w.settimer(timer_ms) (button, is_esc) = ActivateWindow(g, run_type, bb, x, y) return {'button': button, 'is_esc': is_esc, 'grid': g, }
def ProgressWindow(screen, title, text, progress, max_progress=100, width=40, help=None, timer_ms=None, show_cancel=False, run_type=RT_EXECUTEANDPOP): """ Render a panel with a progress bar and a "Cancel" button. """ if progress > max_progress: raise OverflowError("Progress (%d) has exceeded max (%d)." % (progress, max_progress)) scale_proportion = .80 scale_width = int(width * scale_proportion) scale = Scale(scale_width, max_progress) scale.set(progress) g = GridFormHelp(screen, title, help, 1, 3) t = TextboxReflowed(width, text) g.add(t, 0, 0) g.add(scale, 0, 1, padding = (0, 1, 0, 1)) if show_cancel: bb = ButtonBar(screen, [BTN_CANCEL[0]]) g.add(bb, 0, 2, growx = 1) if timer_ms: g.form.w.settimer(timer_ms) (button, is_esc) = ActivateWindow(g, run_type, \ button_bar=bb if show_cancel else None) return {'button': button, 'is_esc': is_esc, 'progress': progress, 'grid': g, }
def ButtonWindow(screen, title, text, allowCancel=1, width=40, entryWidth=20, buttons=['Ok', 'Cancel'], help=None): """ EntryWindow(screen, title, text, prompts, allowCancel = 1, width = 40, entryWidth = 20, buttons = [ 'Ok', 'Cancel' ], help = None): """ from snack import ButtonBar, TextboxReflowed, GridFormHelp bb = ButtonBar(screen, buttons) t = TextboxReflowed(width, text) g = GridFormHelp(screen, title, help, 1, 3) g.add(t, 0, 0, padding=(0, 0, 0, 1)) g.add(bb, 0, 1, growx=1) result = g.runOnce() return [bb.buttonPressed(result)]
def ExtEntryRadioWindow(screen, title, text, prompts, allowCancel=1, width=40, entryWidth=20, buttons=['Ok', 'Cancel'], help=None, radio_prompts=''): bb = ButtonBar(screen, buttons, compact=1) t = TextboxReflowed(width, text) radio_grid = Grid(3, len(radio_prompts)) sg = Grid(2, len(prompts)) max_name_length = 0 for n in prompts: if isinstance(n, types.TupleType): n = n[0] if len(n) > max_name_length: max_name_length = len(n) radioList = parse_radio_prompts(radio_prompts, radio_grid, entryWidth, max_name_length) entryList = [] entry_row = 0 for n in prompts: if isinstance(n, types.TupleType): (n, e) = n if (type(e) in types.StringTypes): e = Entry(entryWidth, e) else: e = Entry(entryWidth) sg.setField(Label(n), 0, entry_row, padding=(0, 0, 1, 0), anchorLeft=1) sg.setField(e, 1, entry_row, anchorLeft=1) entry_row += 1 entryList.append(e) g = GridFormHelp(screen, title, help, 1, 4) g.add(t, 0, 0, padding=(0, 0, 0, 1)) g.add(radio_grid, 0, 1, padding=(0, 0, 0, 1)) g.add(sg, 0, 2, padding=(0, 0, 0, 1)) g.add(bb, 0, 3, growx=1) result = g.runOnce() entryValues = [] for rowRadioList in radioList: for radio, radio_text in rowRadioList: if radio.selected(): entryValues.append(radio_text) break for entry in entryList: entryValues.append(entry.value()) return (result, bb.buttonPressed(result), tuple(entryValues))
def EntryWindow(screen, title, text, prompts, allowCancel=1, width=40, entryWidth=20, buttons=[ 'Ok', 'Cancel' ], help=None, timer_ms=None, anchorLeft=0, anchorRight=1, secondary_message=None, secondary_message_width=None, run_type=RT_EXECUTEANDPOP): # Dustin: Added timer_ms parameter. Added secondary_message arguments. # Added result boolean for whether ESC was pressed. Added # anchorLeft and anchorRight as arguments to this function. Added # secondary_message (test below primary text). Results are now # dictionaries. Added auto_pop parameter. bb = ButtonBar(screen, buttons); t = TextboxReflowed(width, text) count = 0 for n in prompts: count = count + 1 sg = Grid(2, count) count = 0 entryList = [] for n in prompts: if (type(n) == tuple): (n, e) = n if issubclass(e.__class__, str): e = Entry(entryWidth, e) else: e = Entry(entryWidth) sg.setField(Label(n), 0, count, padding=(0, 0, 1, 0), anchorLeft=anchorLeft, anchorRight=anchorRight) sg.setField(e, 1, count, anchorLeft = 1) count = count + 1 entryList.append(e) g = GridFormHelp(screen, title, help, 1, 3 + (1 if secondary_message else 0)) row = 0 g.add(t, 0, row, padding = (0, 0, 0, 1)) row += 1 if secondary_message: if not secondary_message_width: secondary_message_width = width t2 = TextboxReflowed(secondary_message_width, secondary_message) g.add(t2, 0, row, padding = (0, 0, 0, 1)) row += 1 g.add(sg, 0, row, padding = (0, 0, 0, 1)) row += 1 g.add(bb, 0, row, growx = 1) row += 1 if timer_ms: g.form.w.settimer(timer_ms) (button, is_esc) = ActivateWindow(g, run_type, bb) entryValues = [] count = 0 for n in prompts: entryValues.append(entryList[count].value()) count = count + 1 return {'button': button, 'is_esc': is_esc, 'values': tuple(entryValues), 'grid': g, }
def show_menu(self, title, top_node): selection = 0 while True: items = Menuconfig.menu_node_strings(top_node, 0) height = len(items) scroll = 0 if height > self.screen.height - 13: height = self.screen.height - 13 scroll = 1 buttons = [('Save & Build', 'build', 'B'), ('Save & Exit', 'save', 'S'), (' Help ', 'help', 'h'), (' Exit ', 'exit', 'ESC')] buttonbar = ButtonBar(self.screen, buttons) listbox = Listbox(height, scroll=scroll, returnExit=1) count = 0 for string, _ in items: listbox.append(string, count) if (selection == count): listbox.setCurrent(count) count = count + 1 grid = GridFormHelp(self.screen, title, None, 1, 2) grid.add(listbox, 0, 0, padding=(0, 0, 0, 1)) grid.add(buttonbar, 0, 1, growx=1) grid.addHotKey(' ') rc = grid.runOnce() action = buttonbar.buttonPressed(rc) if action and action != 'help': return action if count == 0: continue selection = listbox.current() _, selected_node = items[selection] sym = selected_node.item if action == 'help': prompt, _ = selected_node.prompt if hasattr(selected_node, 'help') and selected_node.help: help = selected_node.help else: help = 'No help available.' ButtonChoiceWindow(screen=self.screen, title="Help on '{}'".format(prompt), text=help, width=60, buttons=[' Ok ']) continue show_submenu = False if type(sym) == Symbol: if rc == ' ': if sym.type == BOOL: sym.set_value('n' if sym.tri_value > 0 else 'y') else: if selected_node.is_menuconfig: show_submenu = True elif sym.type in (STRING, INT, HEX): action, values = EntryWindow( screen=self.screen, title=sym.name, text='Enter a %s value:' % TYPE_TO_STR[sym.type], prompts=[('', sym.str_value)], buttons=[(' Ok ', 'Ok'), ('Cancel', '', 'ESC')]) if action == 'Ok': self.kconf.warnings = [] val = values[0] if sym.type == HEX and not val.startswith('0x'): val = '0x' + val sym.set_value(val) # only fetching triggers range check - how ugly... sym.str_value if len(self.kconf.warnings) > 0: ButtonChoiceWindow(screen=self.screen, title="Invalid entry", text="\n".join( self.kconf.warnings), width=60, buttons=[' Ok ']) self.kconf.warnings = [] elif selected_node.is_menuconfig and type(sym) != Choice: show_submenu = True if show_submenu: submenu_title, _ = selected_node.prompt action = self.show_menu(submenu_title, selected_node.list) if action != 'exit': return action
def display_create_template(screen, title, vm_type, templates, help=None): """Helper function for displaying a form for creating a new VM template""" label_base = Textbox( 40, 2, 'Select %s VM to be used as a basis\n(only stopped VMs are allowed)' % vm_type, 0, 0) base_tmpl = Listbox(7, 1, 0, 30, 1) for vm in templates.keys(): base_tmpl.append(templates[vm], vm) label_newname = Textbox(40, 2, 'Name of the template to be created', 0, 0) spacer1 = Textbox(1, 1, "", 0, 0) spacer2 = Textbox(1, 1, "", 0, 0) entry_newname = Entry(30, 'template_name') bb = ButtonBar(screen, ('Create new template', ('Back to menu', 'back'))) form = GridFormHelp(screen, title, help, 1, 7) form.add(label_base, 0, 0) form.add(base_tmpl, 0, 1) form.add(spacer1, 0, 2) form.add(label_newname, 0, 3) form.add(entry_newname, 0, 4) form.add(spacer2, 0, 5) form.add(bb, 0, 6) form_result = form.runOnce() tmpl_name = entry_newname.value() # remove whitespaces from the template name tmpl_name = re.sub(r'\s', '', tmpl_name) return (bb.buttonPressed(form_result), str(base_tmpl.current()), tmpl_name)
def display_create_template(screen, title, vm_type, templates, help=None): """Helper class for displaying a form for creating a new VM template""" label_base = Textbox(40, 2, 'Select %s VM to be used as a basis\n(only stopped VMs are allowed)' % vm_type, 0, 0) base_tmpl = Listbox(7, 1, 0, 30, 1) for vm in templates.keys(): base_tmpl.append(templates[vm], vm) label_newname = Textbox(40, 2, 'Name of the template to be created', 0, 0) spacer1 = Textbox(1, 1, "", 0, 0) spacer2 = Textbox(1, 1, "", 0, 0) entry_newname = Entry(30, 'template_name') bb = ButtonBar(screen, ('Create new template', ('Back to menu', 'back'))) form = GridFormHelp(screen, title, help, 1, 7) form.add(label_base, 0, 0) form.add(base_tmpl, 0, 1) form.add(spacer1, 0, 2) form.add(label_newname, 0, 3) form.add(entry_newname, 0, 4) form.add(spacer2, 0, 5) form.add(bb, 0, 6) form_result = form.runOnce() tmpl_name = entry_newname.value() # remove whitespaces from the template name tmpl_name = re.sub(r'\s', '', tmpl_name) return (bb.buttonPressed(form_result), str(base_tmpl.current()), tmpl_name)
def AssistantWindow(screen, title, info, width=40, buttons=['Next', 'Previous', 'Return'], help=None): from snack import ButtonBar, TextboxReflowed, GridFormHelp, Label """ EntryWindow(): """ bb = ButtonBar(screen, buttons) rb = AssistantInfoRadioBar(screen, info) t = TextboxReflowed(width, info.getComment()) g = GridFormHelp(screen, title, help, 1, 4) g.add(Label(info.getName()), 0, 0, padding=(0, 0, 1, 0), anchorLeft=0) g.add(t, 0, 1, padding=(0, 0, 0, 1)) g.add(bb, 0, 3, growx=1) g.add(rb, 0, 2, padding=(0, 0, 0, 1)) result = g.runOnce() return (bb.buttonPressed(result), rb.getSelection())
def display_info(screen, title, info_text="Close me, please.", width=50, height=2): """Display information message on information screen""" g = GridFormHelp(screen, title, help, 1, 2) g.add(Textbox(width, height, info_text, 0, 0), 0, 0, padding = (0, 1, 0, 1)) g.add(Button("OK"), 0, 1) g.runOnce()
def ListboxChoiceWindow(screen, title, text, items, buttons = ('Ok', 'Cancel'), width=40, scroll=None, height=-1, default=None, help=None, timer_ms=None, secondary_message=None, secondary_message_width=None, run_type=RT_EXECUTEANDPOP): # Dustin: Added timer_ms parameter. Added secondary_message arguments. # Added result boolean for whether ESC was pressed. Results are now # dictionaries. Added auto_pop parameter. if height == -1: height = len(items) if scroll == None: scroll = len(items) > height bb = ButtonBar(screen, buttons) t = TextboxReflowed(width, text) l = Listbox(height, scroll = scroll, returnExit = 1) count = 0 for item in items: if (type(item) == tuple): (text, key) = item else: text = item key = count if (default == count): default = key elif (default == text): default = key l.append(text, key) count = count + 1 if (default != None): l.setCurrent (default) g = GridFormHelp(screen, title, help, 1, 3 + (1 if secondary_message else 0)) row = 0 g.add(t, 0, row) row += 1 if secondary_message: if not secondary_message_width: secondary_message_width = width t2 = TextboxReflowed(secondary_message_width, secondary_message) g.add(t2, 0, row, padding = (0, 0, 0, 1)) row += 1 g.add(l, 0, row, padding = (0, 1, 0, 1)) row += 1 g.add(bb, 0, row, growx = 1) row += 1 if timer_ms: g.form.w.settimer(timer_ms) (button, is_esc) = ActivateWindow(g, run_type, bb) return {'button': button, 'is_esc': is_esc, 'grid': g, # A hack. There's no count method. 'selected': l.current() if l.key2item else None, }
def CheckboxListWindow(screen, title, text, items, buttons=(BTN_OK[0], BTN_CANCEL[0]), width=40, scroll=0, default=None, help=None, timer_ms=None, secondary_message=None, secondary_message_width=None, run_type=RT_EXECUTEANDPOP, default_check_state=False, default_check_states=None): if not default_check_states: default_check_states = [default_check_state for i in xrange(len(items))] elif len(default_check_states) != len(items): raise Exception("Number (%d) of check states does not match number of " "items (%d)." % (len(default_check_states), len(items))) primary_message_height = 1 button_height = 1 checklist_margin = 0 rows = primary_message_height + \ button_height + \ (2 if secondary_message else 0) + \ len(items) + \ checklist_margin bb = ButtonBar(screen, buttons) t = TextboxReflowed(width, text) g = GridFormHelp(screen, title, help, 1, rows) row = 0 g.add(t, 0, row) row += 1 if secondary_message: if not secondary_message_width: secondary_message_width = width t2 = TextboxReflowed(secondary_message_width, secondary_message) g.add(t2, 0, row, padding = (0, 1, 0, 0)) row += 1 checkboxes = [] i = 0 for item in items: if (type(item) == types.TupleType): (text, state) = item else: text = item state = default_check_state padding = [0, 0, 0, 0] if i == 0: padding[1] = 1 if i == len(items) - 1: padding[3] = 1 checkbox = Checkbox(text, int(state)) checkboxes.append(checkbox) g.add(checkbox, 0, row, padding) row += 1 i += 1 g.add(bb, 0, row, growx = 1) row += 1 if timer_ms: g.form.w.settimer(timer_ms) (button, is_esc) = ActivateWindow(g, run_type, bb) values = [checkbox.selected() for checkbox in checkboxes] return {'values': values, 'button': button, 'is_esc': is_esc, 'grid': g, }