def __init__(self, controller): self.controller = controller self.hline = urwid.AttrWrap(urwid.SolidFill(u'_'), 'line') self.mode_buttons = [] self.refresh_rate_ctrl = urwid.Edit(('bold text', u'Refresh[s]:'), self.controller.refresh_rate) # Visible graphs are the graphs currently displayed, this is a # subset of the available graphs for display self.visible_graphs = {} self.graph_place_holder = urwid.WidgetPlaceholder(urwid.Pile([])) self.main_window_w = [] self.stress_menu = StressMenu(self.on_menu_close) self.help_menu = HelpMenu(self.on_menu_close) self.about_menu = AboutMenu(self.on_menu_close) self.temp_sensors_menu = TempSensorsMenu(self.on_sensors_menu_close) self.global_data = GlobalData(is_admin) self.stress_menu.sqrt_workers = str(self.global_data.num_cpus) self.left_margin = 0 self.top_margin = 0 self.v_relative = 50 self.h_relative = 50 urwid.WidgetPlaceholder.__init__(self, self.main_window()) urwid.connect_signal(self.refresh_rate_ctrl, 'change', self.update_refresh_rate)
def __init__(self, controller): # constants self.left_margin = 0 self.top_margin = 0 # main control self.controller = controller self.main_window_w = [] # general urwid items clock_text = seconds_to_text(self.controller.stress_time) self.clock_view = urwid.Text(('bold text', clock_text), align="center") self.refresh_rate_ctrl = urwid.Edit(('bold text', u'Refresh[s]:'), self.controller.refresh_rate) self.hline = urwid.AttrWrap(urwid.SolidFill(u'_'), 'line') self.mode_buttons = [] # Visible graphs are the graphs currently displayed, this is a # subset of the available graphs for display self.visible_graphs = {} self.graph_place_holder = urwid.WidgetPlaceholder(urwid.Pile([])) # construct sources possible_source = [TempSource(self.controller.temp_thresh), FreqSource(), UtilSource(), RaplPowerSource()] self.source_list = [s for s in possible_source if s.get_is_available()] # construct the variouse menus during init phase self.stress_menu = StressMenu(self.on_menu_close) self.help_menu = HelpMenu(self.on_menu_close) self.about_menu = AboutMenu(self.on_menu_close) self.sensors_menu = SensorsMenu(self.on_sensors_menu_close, self.source_list) self.global_data = GlobalData(is_admin) self.stress_menu.sqrt_workers = str(self.global_data.num_cpus) # call super urwid.WidgetPlaceholder.__init__(self, self.main_window()) urwid.connect_signal(self.refresh_rate_ctrl, 'change', self.update_refresh_rate)
def __init__(self, controller, args): self.controller = controller self.custom_temp = args.custom_temp self.hline = urwid.AttrWrap(urwid.SolidFill(u'_'), 'line') self.mode_buttons = [] self.visible_graphs = {} self.graph_place_holder = urwid.WidgetPlaceholder(urwid.Pile([])) self.main_window_w = [] self.stress_menu = StressMenu(self.on_menu_close) self.help_menu = HelpMenu(self.on_menu_close) self.about_menu = AboutMenu(self.on_menu_close) self.global_data = GlobalData(is_admin) self.stress_menu.sqrt_workers = str(self.global_data.num_cpus) urwid.WidgetPlaceholder.__init__(self, self.main_window())
class GraphView(urwid.WidgetPlaceholder): """ A class responsible for providing the application's interface and graph display. The GraphView can change the state of the graph, since it provides the UI The change is state should be reflected in the GraphController """ def __init__(self, controller): # constants self.left_margin = 0 self.top_margin = 0 # main control self.controller = controller self.main_window_w = [] # general urwid items clock_text = seconds_to_text(self.controller.stress_time) self.clock_view = urwid.Text(('bold text', clock_text), align="center") self.refresh_rate_ctrl = urwid.Edit(('bold text', u'Refresh[s]:'), self.controller.refresh_rate) self.hline = urwid.AttrWrap(urwid.SolidFill(u'_'), 'line') self.mode_buttons = [] # Visible graphs are the graphs currently displayed, this is a # subset of the available graphs for display self.visible_graphs = {} self.graph_place_holder = urwid.WidgetPlaceholder(urwid.Pile([])) # construct sources possible_source = [TempSource(self.controller.temp_thresh), FreqSource(), UtilSource(), RaplPowerSource()] self.source_list = [s for s in possible_source if s.get_is_available()] # construct the variouse menus during init phase self.stress_menu = StressMenu(self.on_menu_close) self.help_menu = HelpMenu(self.on_menu_close) self.about_menu = AboutMenu(self.on_menu_close) self.sensors_menu = SensorsMenu(self.on_sensors_menu_close, self.source_list) self.global_data = GlobalData(is_admin) self.stress_menu.sqrt_workers = str(self.global_data.num_cpus) # call super urwid.WidgetPlaceholder.__init__(self, self.main_window()) urwid.connect_signal(self.refresh_rate_ctrl, 'change', self.update_refresh_rate) def update_refresh_rate(self, edit, new_refresh_rate): try: if float(new_refresh_rate) <= 0.001: pass else: self.controller.refresh_rate = new_refresh_rate except ValueError: self.controller.refresh_rate = '2.0' def update_displayed_information(self): """ Update all the graphs that are being displayed """ for key, val in self.available_summaries.items(): val.source.update() for g in self.visible_graphs.values(): g.update_displayed_graph_data() # update graph summery for s in self.available_summaries.values(): s.update() # Only update clock if not is stress mode if self.controller.mode.get_current_mode() != 'Monitor': self.controller.stress_time = (timeit.default_timer() - self.controller.stress_start_time) self.clock_view.set_text(('bold text', seconds_to_text( int(self.controller.stress_time)))) def on_reset_button(self, w): """Reset graph data and display empty graph""" for g in self.visible_graphs.values(): g.reset() for g in self.graphs.values(): try: g.source.reset() except NotImplementedError: pass # Reset clock self.controller.stress_time = 0 self.update_displayed_information() def on_menu_close(self): """Return to main screen""" self.original_widget = self.main_window_w def on_sensors_menu_close(self, update): """Return to main screen and update sensor that are active in the view""" logging.info("closing sensor menu") logging.info("sensor update is: " + str(update)) if update: for sensor, visible_sensors in \ self.sensors_menu.sensor_current_active_dict.items(): logging.info(str(visible_sensors)) self.graphs[sensor].set_visible_graphs(visible_sensors) self.original_widget = self.main_window_w def on_stress_menu_open(self, w): """Open stress options""" self.original_widget = urwid.Overlay(self.stress_menu.main_window, self.original_widget, ('relative', self.left_margin), self.stress_menu.get_size()[1], ('relative', self.top_margin), self.stress_menu.get_size()[0]) def on_help_menu_open(self, w): """Open Help menu""" self.original_widget = urwid.Overlay(self.help_menu.main_window, self.original_widget, ('relative', self.left_margin), self.help_menu.get_size()[1], ('relative', self.top_margin), self.help_menu.get_size()[0]) def on_about_menu_open(self, w): """Open About menu""" self.original_widget = urwid.Overlay(self.about_menu.main_window, self.original_widget, ('relative', self.left_margin), self.about_menu.get_size()[1], ('relative', self.top_margin), self.about_menu.get_size()[0]) def on_sensors_menu_open(self, w): """Open Sensor menu on top of existing frame""" self.original_widget = urwid.Overlay( self.sensors_menu.main_window, self.original_widget, ('relative', self.left_margin), self.sensors_menu.get_size()[1], ('relative', self.top_margin), self.sensors_menu.get_size()[0]) def on_mode_button(self, my_button, state): """Notify the controller of a new mode setting.""" if state: # The new mode is the label of the button self.controller.set_mode(my_button.get_label()) self.controller.start_stress() for graph in self.graphs: graph.update_displayed_graph_data() def on_mode_change(self, m): """Handle external mode change by updating radio buttons.""" for rb in self.mode_buttons: if rb.get_label() == m: rb.set_state(True, do_callback=False) break def on_unicode_checkbox(self, w=None, state=False): """Enable smooth edges if utf-8 is supported""" logging.debug("unicode State is " + str(state)) # Update the controller to the state of the checkbox self.controller.smooth_graph_mode = state if state: self.hline = urwid.AttrWrap( urwid.SolidFill(u'\N{LOWER ONE QUARTER BLOCK}'), 'line') else: self.hline = urwid.AttrWrap(urwid.SolidFill(u'_'), 'line') for g_name, g in self.graphs.items(): g.set_smooth_colors(state) # g.update_displayed_graph_data() self.show_graphs() def exit_program(self, w=None): """ Kill all stress operations upon exit""" kill_child_processes(self.controller.mode.get_stress_process()) raise urwid.ExitMainLoop() def save_settings(self, w=None): """ Save the current configuration to a user config file """ if not user_config_dir_exists(): make_user_config_dir() conf = configparser.ConfigParser() config_file = get_user_config_file() with open(config_file, 'w') as cfgfile: conf.add_section('GraphControll') conf.set('GraphControll', 'refresh', str( self.controller.refresh_rate)) conf.set('GraphControll', 'UTF8', str( self.controller.smooth_graph_mode)) for graph_name in self.available_graphs.keys(): try: if graph_name in self.visible_graphs: conf.set('GraphControll', graph_name, 'True') else: conf.set('GraphControll', graph_name, 'False') except (AttributeError, configparser.NoOptionError, configparser.NoSectionError): pass if self.controller.temp_thresh is not None: logging.debug("Custom temp threshold set to " + str(self.controller.temp_thresh)) try: conf.set('TempControll', 'threshold', self.controller.temp_thresh) except(AttributeError, configparser.NoOptionError, configparser.NoSectionError): pass # Save settings for sensors menu conf.add_section('Sensors') conf.write(cfgfile) def graph_controls(self, conf): """ Display sidebar controls. i.e. buttons, and controls""" modes = self.controller.get_modes() # setup mode radio buttons group = [] for m in modes: rb = radio_button(group, m, self.on_mode_button) self.mode_buttons.append(rb) # Create list of buttons control_options = [button("Reset", self.on_reset_button)] if stress_installed: control_options.append(button('Stress Options', self.on_stress_menu_open)) control_options.append(button('Sensors', self.on_sensors_menu_open)) control_options.append(button('Help', self.on_help_menu_open)) control_options.append(button('About', self.on_about_menu_open)) # Create the menu animate_controls = urwid.GridFlow(control_options, 18, 2, 0, 'center') # Create smooth graph selection button default_smooth = self.controller.smooth_graph_mode if urwid.get_encoding_mode() == "utf8": unicode_checkbox = urwid.CheckBox( "Smooth Graph", state=default_smooth, on_state_change=self.on_unicode_checkbox) # Init the state of the graph accoding to the selected mode self.on_unicode_checkbox(state=default_smooth) else: unicode_checkbox = urwid.Text( "UTF-8 encoding not detected") install_stress_message = urwid.Text("") if not stress_installed: install_stress_message = urwid.Text( ('button normal', u"(N/A) install stress")) # Disable graphs the user selected not to display in config file # TODO: Get this from graph state graphs_available_state = dict() for g in self.available_graphs.values(): try: graphs_available_state[g.get_graph_name()] = conf.getboolean( 'GraphControll', g.get_graph_name()) except(AttributeError, configparser.NoOptionError, configparser.NoSectionError): graphs_available_state[g.get_graph_name()] = True graph_checkboxes = [urwid.CheckBox(x.get_graph_name(), graphs_available_state[x.get_graph_name()], on_state_change=lambda w, state, x=x: self.change_checkbox_state(x, state)) for x in self.available_graphs.values()] buttons = [urwid.Text(('bold text', u"Modes"), align="center"), ] + self.mode_buttons + [ install_stress_message, urwid.LineBox(self.clock_view), urwid.Divider(), urwid.Text(('bold text', u"Control Options"), align="center"), animate_controls, urwid.Divider(), self.refresh_rate_ctrl, urwid.Divider(), urwid.LineBox(urwid.Pile(graph_checkboxes)), urwid.LineBox(unicode_checkbox), urwid.Divider(), button("Save Settings", self.save_settings), urwid.Divider(), button("Quit", self.exit_program), ] return buttons def change_checkbox_state(self, x, state): if state: self.visible_graphs[x.get_graph_name()] = x else: del self.visible_graphs[x.get_graph_name()] self.show_graphs() def show_graphs(self): """Show a pile of the graph selected for dislpay""" elements = itertools.chain.from_iterable( ([graph, ('fixed', 1, self.hline)] for graph in self.visible_graphs.values())) self.graph_place_holder.original_widget = urwid.Pile(elements) @staticmethod def cpu_stats(): """Read and display processor name """ cpu_name = urwid.Text("CPU Name N/A", align="center") try: cpu_name = urwid.Text(get_processor_name().strip(), align="center") except OSError: logging.info("CPU name not available") cpu_stats = [cpu_name, urwid.Divider()] return cpu_stats def graph_stats(self): fixed_stats = [] for key, val in self.available_summaries.items(): fixed_stats += val.get_text_item_list() fixed_stats += [urwid.Text('')] # return fixed_stats pile widget return urwid.Pile(fixed_stats) def main_window(self): # initiating the graphs self.graphs = OrderedDict() self.summaries = OrderedDict() # construct frequency graph and source for source in self.source_list: source_name = source.get_source_name() color_pallet = source.get_pallet() alert_pallet = source.get_alert_pallet() self.graphs[source_name] = StuiBarGraphVector( source, color_pallet[0], color_pallet[1], color_pallet[2], color_pallet[3], len(source.get_sensor_list()), self.sensors_menu.sensor_current_active_dict[source_name], alert_colors=alert_pallet ) self.summaries[source_name] = SummaryTextList( self.graphs[source_name].source ) fan_source = FanSource() if fan_source.get_is_available(): self.summaries[fan_source.get_source_name()] = SummaryTextList( fan_source) # only interested in available graph self.available_graphs = OrderedDict( (key, val) for key, val in self.graphs.items() if val.get_is_available()) self.available_summaries = OrderedDict( (key, val) for key, val in self.summaries.items() if val.get_is_available()) self.visible_graphs = self.available_graphs # Remove graphs from shown graphs if user configured them out # TODO: get this information from the state conf = self.controller.conf for graph_name in self.available_graphs.keys(): try: if conf.getboolean('GraphControll', graph_name) is False: del self.visible_graphs[graph_name] except (AttributeError, configparser.NoOptionError, ValueError, configparser.NoSectionError): pass self.show_graphs() cpu_stats = self.cpu_stats() graph_controls = self.graph_controls(conf) graph_stats = self.graph_stats() text_col = ViListBox(urwid.SimpleListWalker(cpu_stats + graph_controls + [urwid.Divider()] + [graph_stats])) vline = urwid.AttrWrap(urwid.SolidFill(u'\u2502'), 'line') w = urwid.Columns([ ('fixed', 20, text_col), ('fixed', 1, vline), ('weight', 2, self.graph_place_holder), ], dividechars=1, focus_column=0) w = urwid.Padding(w, ('fixed left', 1), ('fixed right', 0)) w = urwid.AttrWrap(w, 'body') w = urwid.LineBox(w) w = urwid.AttrWrap(w, 'line') self.main_window_w = w return self.main_window_w
class GraphView(urwid.WidgetPlaceholder): """ A class responsible for providing the application's interface and graph display. The GraphView can change the state of the graph, since it provides the UI The change is state should be reflected in the GraphController """ def __init__(self, controller): self.controller = controller self.hline = urwid.AttrWrap(urwid.SolidFill(u'_'), 'line') self.mode_buttons = [] self.refresh_rate_ctrl = urwid.Edit(('bold text', u'Refresh[s]:'), self.controller.refresh_rate) # Visible graphs are the graphs currently displayed, this is a # subset of the available graphs for display self.visible_graphs = {} self.graph_place_holder = urwid.WidgetPlaceholder(urwid.Pile([])) self.main_window_w = [] self.stress_menu = StressMenu(self.on_menu_close) self.help_menu = HelpMenu(self.on_menu_close) self.about_menu = AboutMenu(self.on_menu_close) self.temp_sensors_menu = TempSensorsMenu(self.on_sensors_menu_close) self.global_data = GlobalData(is_admin) self.stress_menu.sqrt_workers = str(self.global_data.num_cpus) self.left_margin = 0 self.top_margin = 0 self.v_relative = 50 self.h_relative = 50 urwid.WidgetPlaceholder.__init__(self, self.main_window()) urwid.connect_signal(self.refresh_rate_ctrl, 'change', self.update_refresh_rate) def update_refresh_rate(self, edit, new_refresh_rate): try: if float(new_refresh_rate) <= 0.001: pass else: self.controller.refresh_rate = new_refresh_rate except (ValueError): self.controller.refresh_rate = '2.0' def update_displayed_information(self): """ Update all the graphs that are being displayed """ for key, val in self.available_summaries.items(): val.source.update() for g in self.visible_graphs.values(): g.update_displayed_graph_data() for s in self.available_summaries.values(): s.update() def on_reset_button(self, w): """Reset graph data and display empty graph""" for g in self.visible_graphs.values(): g.reset() for g in self.graphs.values(): try: g.source.reset() except (NotImplementedError): pass self.update_displayed_information() def on_menu_close(self): """Return to main screen""" self.original_widget = self.main_window_w def on_sensors_menu_close(self): """Return to main screen and update sensor""" if self.temp_sensors_menu.current_active_mode: logging.info("State is not None") self.controller.custom_temp = ( self.temp_sensors_menu.current_active_mode) self.__init__(self.controller) logging.info("Temp sensor updated to " + self.controller.custom_temp) else: logging.info("Temp sensor is None") self.original_widget = self.main_window_w def on_stress_menu_open(self, w): """Open stress options""" self.original_widget = urwid.Overlay(self.stress_menu.main_window, self.original_widget, ('relative', self.left_margin), self.stress_menu.get_size()[1], ('relative', self.top_margin), self.stress_menu.get_size()[0]) def on_help_menu_open(self, w): """Open Help menu""" self.original_widget = urwid.Overlay(self.help_menu.main_window, self.original_widget, ('relative', self.left_margin), self.help_menu.get_size()[1], ('relative', self.top_margin), self.help_menu.get_size()[0]) def on_about_menu_open(self, w): """Open About menu""" self.original_widget = urwid.Overlay(self.about_menu.main_window, self.original_widget, ('relative', self.left_margin), self.about_menu.get_size()[1], ('relative', self.top_margin), self.about_menu.get_size()[0]) def on_temp_sensors_menu_open(self, w): """Open About menu""" self.original_widget = urwid.Overlay( self.temp_sensors_menu.main_window, self.original_widget, ('relative', self.left_margin), self.temp_sensors_menu.get_size()[1], ('relative', self.top_margin), self.temp_sensors_menu.get_size()[0]) def on_mode_button(self, button, state): """Notify the controller of a new mode setting.""" if state: # The new mode is the label of the button self.controller.set_mode(button.get_label()) self.controller.start_stress() def on_mode_change(self, m): """Handle external mode change by updating radio buttons.""" for rb in self.mode_buttons: if rb.get_label() == m: rb.set_state(True, do_callback=False) break def on_unicode_checkbox(self, w=None, state=False): """Enable smooth edges if utf-8 is supported""" logging.debug("unicode State is " + str(state)) # Update the controller to the state of the checkbox self.controller.smooth_graph_mode = state if state: self.hline = urwid.AttrWrap( urwid.SolidFill(u'\N{LOWER ONE QUARTER BLOCK}'), 'line') else: self.hline = urwid.AttrWrap(urwid.SolidFill(u'_'), 'line') for g_name, g in self.graphs.items(): g.set_smooth_colors(state) self.show_graphs() def exit_program(self, w=None): """ Kill all stress operations upon exit""" kill_child_processes(self.controller.mode.get_stress_process()) raise urwid.ExitMainLoop() def save_settings(self, w=None): """ Save the current configuration to a user config file """ if not user_config_dir_exists(): make_user_config_dir() conf = configparser.ConfigParser() config_file = get_user_config_file() with open(config_file, 'w') as cfgfile: conf.add_section('GraphControll') conf.set('GraphControll', 'refresh', str(self.controller.refresh_rate)) conf.set('GraphControll', 'UTF8', str(self.controller.smooth_graph_mode)) for graph_name in self.available_graphs.keys(): try: if graph_name in self.visible_graphs: conf.set('GraphControll', graph_name, 'True') else: conf.set('GraphControll', graph_name, 'False') except (AttributeError, configparser.NoOptionError, configparser.NoSectionError): pass # Writing temp sensor conf.add_section('TempControll') if self.controller.custom_temp is not None: logging.debug("Custom temp sensor is " + self.controller.custom_temp) try: conf.set('TempControll', 'sensor', self.controller.custom_temp) except (AttributeError, configparser.NoOptionError, configparser.NoSectionError): pass if self.controller.temp_thresh is not None: logging.debug("Custom temp threshold set to " + str(self.controller.temp_thresh)) try: conf.set('TempControll', 'threshold', self.controller.temp_thresh) except (AttributeError, configparser.NoOptionError, configparser.NoSectionError): pass conf.write(cfgfile) def graph_controls(self, conf): """ Dislplay sidebar controls. i.e. buttons, and controls""" modes = self.controller.get_modes() # setup mode radio buttons group = [] for m in modes: rb = radio_button(group, m, self.on_mode_button) self.mode_buttons.append(rb) # Create list of buttons control_options = [button("Reset", self.on_reset_button)] if stress_installed: control_options.append( button('Stress Options', self.on_stress_menu_open)) control_options.append( button('Temp Sensors', self.on_temp_sensors_menu_open)) control_options.append(button('Help', self.on_help_menu_open)) control_options.append(button('About', self.on_about_menu_open)) # Create the menu animate_controls = urwid.GridFlow(control_options, 18, 2, 0, 'center') # Create smooth graph selection button default_smooth = self.controller.smooth_graph_mode if urwid.get_encoding_mode() == "utf8": unicode_checkbox = urwid.CheckBox( "Smooth Graph", state=default_smooth, on_state_change=self.on_unicode_checkbox) # Init the state of the graph accoding to the selected mode self.on_unicode_checkbox(state=default_smooth) else: unicode_checkbox = urwid.Text("UTF-8 encoding not detected") install_stress_message = urwid.Text("") if not stress_installed: install_stress_message = urwid.Text( ('button normal', u"(N/A) install stress")) # Disable graphs the user selected not to display in config file # TODO: Get this from graph state graphs_available_state = dict() for g in self.available_graphs.values(): try: graphs_available_state[g.get_graph_name()] = conf.getboolean( 'GraphControll', g.get_graph_name()) except (AttributeError, configparser.NoOptionError, configparser.NoSectionError): graphs_available_state[g.get_graph_name()] = True graph_checkboxes = [ urwid.CheckBox(x.get_graph_name(), graphs_available_state[x.get_graph_name()], on_state_change=lambda w, state, x=x: self. change_checkbox_state(x, state)) for x in self.available_graphs.values() ] unavalable_graphs = [ urwid.Text(("[N/A] " + x.get_graph_name())) for x in self.graphs.values() if x.source.get_is_available() is False ] graph_checkboxes += unavalable_graphs buttons = [ urwid.Text(('bold text', u"Modes"), align="center"), ] + self.mode_buttons + [ install_stress_message, urwid.Divider(), urwid.Text(('bold text', u"Control Options"), align="center"), animate_controls, urwid.Divider(), self.refresh_rate_ctrl, urwid.Divider(), urwid.LineBox(urwid.Pile(graph_checkboxes)), urwid.LineBox(unicode_checkbox), urwid.Divider(), button("Save Settings", self.save_settings), urwid.Divider(), button("Quit", self.exit_program), ] return buttons def change_checkbox_state(self, x, state): if state: self.visible_graphs[x.get_graph_name()] = x else: del self.visible_graphs[x.get_graph_name()] self.show_graphs() def show_graphs(self): """Show a pile of the graph selected for dislpay""" elements = itertools.chain.from_iterable( ([graph, ('fixed', 1, self.hline)] for graph in self.visible_graphs.values())) self.graph_place_holder.original_widget = urwid.Pile(elements) def cpu_stats(self): """Read and display processor name """ cpu_name = urwid.Text("CPU Name N/A", align="center") try: cpu_name = urwid.Text(get_processor_name().strip(), align="center") except (OSError): logging.info("CPU name not available") cpu_stats = [cpu_name, urwid.Divider()] return cpu_stats def graph_stats(self): fixed_stats = [] for key, val in self.available_summaries.items(): fixed_stats += val.get_text_item_list() return fixed_stats def main_window(self): # initiating the graphs self.graphs = OrderedDict() self.summaries = OrderedDict() # TODO: Update to find sensors automatically ''' freq_source = FreqSource(is_admin) self.graphs[freq_source.get_source_name()] = StuiBarGraph( freq_source, 'freq light', 'freq dark', 'freq light smooth', 'freq dark smooth' ) self.summaries[freq_source.get_source_name()] = SummaryTextList( freq_source ) ''' util_source = UtilSource() self.graphs[util_source.get_source_name()] = StuiBarGraph( util_source, 'util light', 'util dark', 'util light smooth', 'util dark smooth') self.summaries[util_source.get_source_name()] = SummaryTextList( util_source) temp_source = TempSource(self.controller.custom_temp, self.controller.temp_thresh) if self.controller.script_hooks_enabled: temp_source.add_edge_hook( self.controller.script_loader.load_script( temp_source.__class__.__name__, 30000) ) # Invoke threshold script every 30s while threshold is exceeded. alert_colors = [ 'high temp light', 'high temp dark', 'high temp light smooth', 'high temp dark smooth' ] self.graphs[temp_source.get_source_name()] = StuiBarGraph( temp_source, 'temp light', 'temp dark', 'temp light smooth', 'temp dark smooth', alert_colors=alert_colors) self.summaries[temp_source.get_source_name()] = SummaryTextList( temp_source, 'high temp txt') mem_source = MemorySource() self.graphs[mem_source.get_source_name()] = StuiBarGraph( mem_source, 'power dark', 'power light', 'power dark smooth', 'power light smooth') self.summaries[mem_source.get_source_name()] = SummaryTextList( mem_source) #fan_source = FanSource(self.controller.args.custom_fan) #self.summaries[fan_source.get_source_name()] = SummaryTextList( # fan_source) # only interested in available graph self.available_graphs = OrderedDict( (key, val) for key, val in self.graphs.items() if val.get_is_available()) self.available_summaries = OrderedDict( (key, val) for key, val in self.summaries.items() if val.get_is_available()) self.visible_graphs = self.available_graphs.copy() # Remove graphs from shown graphs if user configed them out # TODO: get this information from the state conf = self.controller.conf for graph_name in self.available_graphs.keys(): try: if conf.getboolean('GraphControll', graph_name) is False: del self.visible_graphs[graph_name] except (AttributeError, configparser.NoOptionError, ValueError, configparser.NoSectionError): pass self.show_graphs() cpu_stats = self.cpu_stats() graph_controls = self.graph_controls(conf) graph_stats = self.graph_stats() text_col = ViListBox( urwid.SimpleListWalker(cpu_stats + graph_controls + [urwid.Divider()] + graph_stats)) vline = urwid.AttrWrap(urwid.SolidFill(u'\u2502'), 'line') w = urwid.Columns([ ('fixed', 20, text_col), ('fixed', 1, vline), ('weight', 2, self.graph_place_holder), ], dividechars=1, focus_column=0) w = urwid.Padding(w, ('fixed left', 1), ('fixed right', 0)) w = urwid.AttrWrap(w, 'body') w = urwid.LineBox(w) w = urwid.AttrWrap(w, 'line') self.main_window_w = w return self.main_window_w
class GraphView(urwid.WidgetPlaceholder): """ A class responsible for providing the application's interface and graph display. """ def __init__(self, controller, args): self.controller = controller self.custom_temp = args.custom_temp self.args = args self.hline = urwid.AttrWrap(urwid.SolidFill(u'_'), 'line') self.mode_buttons = [] self.refresh_rate_ctrl = urwid.Edit(('bold text', u'Refresh[s]:'), self.controller.refresh_rate) self.visible_graphs = {} self.graph_place_holder = urwid.WidgetPlaceholder(urwid.Pile([])) self.main_window_w = [] self.stress_menu = StressMenu(self.on_menu_close) self.help_menu = HelpMenu(self.on_menu_close) self.about_menu = AboutMenu(self.on_menu_close) self.temp_sensors_menu = TempSensorsMenu(self.on_sensors_menu_close) self.global_data = GlobalData(is_admin) self.stress_menu.sqrt_workers = str(self.global_data.num_cpus) self.left_margin = 0 self.top_margin = 0 self.v_relative = 50 self.h_relative = 50 urwid.WidgetPlaceholder.__init__(self, self.main_window()) urwid.connect_signal(self.refresh_rate_ctrl, 'change', self.update_refresh_rate) def update_refresh_rate(self, edit, new_refresh_rate): try: if float(new_refresh_rate) <= 0.001: pass else: self.controller.refresh_rate = new_refresh_rate except: self.controller.refresh_rate = '1.0' def update_displayed_information(self): """ Update all the graphs that are being displayed """ for key,val in self.graphs.items(): val.source.update() for g in self.visible_graphs.values(): g.update_displayed_graph_data() for s in self.available_summaries.values(): s.update() def on_reset_button(self, w): """Reset graph data and display empty graph""" for g in self.visible_graphs.values(): g.reset() for g in self.graphs.values(): try: g.source.reset() except NotImplementedError: pass self.update_displayed_information() def on_menu_close(self): """Return to main screen""" self.original_widget = self.main_window_w def on_sensors_menu_close(self): """Return to main screen and update sensor""" if self.temp_sensors_menu.current_active_mode: logging.info("State is not None") self.args.custom_temp = self.temp_sensors_menu.current_active_mode self.__init__(self.controller, self.args) logging.info("Temp sensor updated to " + self.args.custom_temp) else: logging.info("Temp sensor is None") self.original_widget = self.main_window_w def on_stress_menu_open(self, w): """Open stress options""" self.original_widget = urwid.Overlay(self.stress_menu.main_window, self.original_widget, ('relative', self.left_margin), self.stress_menu.get_size()[1], ('relative', self.top_margin), self.stress_menu.get_size()[0]) def on_help_menu_open(self, w): """Open Help menu""" self.original_widget = urwid.Overlay(self.help_menu.main_window, self.original_widget, ('relative', self.left_margin), self.help_menu.get_size()[1], ('relative', self.top_margin), self.help_menu.get_size()[0]) def on_about_menu_open(self, w): """Open About menu""" self.original_widget = urwid.Overlay(self.about_menu.main_window, self.original_widget, ('relative', self.left_margin), self.about_menu.get_size()[1], ('relative', self.top_margin), self.about_menu.get_size()[0]) def on_temp_sensors_menu_open(self, w): """Open About menu""" self.original_widget = urwid.Overlay(self.temp_sensors_menu.main_window, self.original_widget, ('relative', self.left_margin), self.temp_sensors_menu.get_size()[1], ('relative', self.top_margin), self.temp_sensors_menu.get_size()[0]) def on_mode_button(self, button, state): """Notify the controller of a new mode setting.""" if state: # The new mode is the label of the button self.controller.set_mode(button.get_label()) self.controller.start_stress() def on_mode_change(self, m): """Handle external mode change by updating radio buttons.""" for rb in self.mode_buttons: if rb.get_label() == m: rb.set_state(True, do_callback=False) break def on_unicode_checkbox(self, w, state): """Enable smooth edges if utf-8 is supported""" logging.debug("unicode State is " + str(state)) if state: self.hline = urwid.AttrWrap(urwid.SolidFill(u'\N{LOWER ONE QUARTER BLOCK}'), 'line') else: self.hline = urwid.AttrWrap(urwid.SolidFill(u'_'), 'line') for g_name,g in self.graphs.items(): g.set_smooth_colors(state) self.show_graphs() def exit_program(self, w=None): """ Kill all stress operations upon exit""" try: kill_child_processes(self.controller.mode.get_stress_process()) except: logging.debug('Could not kill process') raise urwid.ExitMainLoop() def graph_controls(self): """ Dislplay sidebar controls. i.e. buttons, and controls""" modes = self.controller.get_modes() # setup mode radio buttons group = [] for m in modes: rb = radio_button(group, m, self.on_mode_button) self.mode_buttons.append(rb) # Create list of buttons control_options = [button("Reset", self.on_reset_button)] if stress_installed: control_options.append(button('Stress Options', self.on_stress_menu_open)) control_options.append(button('Temp Sensors', self.on_temp_sensors_menu_open)) control_options.append(button('Help', self.on_help_menu_open)) control_options.append(button('About', self.on_about_menu_open)) # Create the menu animate_controls = urwid.GridFlow(control_options, 18, 2, 0, 'center') if urwid.get_encoding_mode() == "utf8": unicode_checkbox = urwid.CheckBox( "Smooth Graph", state=False, on_state_change=self.on_unicode_checkbox) else: unicode_checkbox = urwid.Text( "UTF-8 encoding not detected") install_stress_message = urwid.Text("") if not stress_installed: install_stress_message = urwid.Text("\nstress not installed") graph_checkboxes = [urwid.CheckBox(x.get_graph_name(), state=True, on_state_change=lambda w, state, x=x: self.change_checkbox_state(x, state)) for x in self.available_graphs.values()] unavalable_graphs = [urwid.Text(( "[N/A] " + x.get_graph_name()) ) for x in self.graphs.values() if x.source.get_is_available() == False] graph_checkboxes += unavalable_graphs buttons = [urwid.Text(('bold text', u"Modes"), align="center"), ] + self.mode_buttons + [ install_stress_message, urwid.Divider(), urwid.Text(('bold text', u"Control Options"), align="center"), animate_controls, urwid.Divider(), self.refresh_rate_ctrl, urwid.Divider(), urwid.LineBox(urwid.Pile(graph_checkboxes)), urwid.LineBox(unicode_checkbox), urwid.Divider(), button("Quit", self.exit_program), ] return buttons def change_checkbox_state(self, x, state): if state: self.visible_graphs[x.get_graph_name()] = x else: del self.visible_graphs[x.get_graph_name()] self.show_graphs() def show_graphs(self): """Show a pile of the graph selected for dislpay""" elements = itertools.chain.from_iterable(([graph, ('fixed', 1, self.hline)] for graph in self.visible_graphs.values())) self.graph_place_holder.original_widget = urwid.Pile(elements) def cpu_stats(self): """Read and display processor name """ cpu_name = urwid.Text("CPU Name N/A", align="center") try: cpu_name = urwid.Text(get_processor_name().strip(), align="center") except: logging.info("CPU name not available") cpu_stats = [cpu_name, urwid.Divider()] return cpu_stats def graph_stats(self): fixed_stats = [] for key, val in self.available_summaries.items(): fixed_stats += val.get_text_item_list() return fixed_stats def main_window(self): # initiating the graphs self.graphs = OrderedDict() self.summaries = OrderedDict() # TODO: Update to find sensors automatically freq_source = FreqSource(is_admin) self.graphs[freq_source.get_source_name()] = StuiBarGraph(freq_source, 'freq light', 'freq dark', 'freq light smooth', 'freq dark smooth') self.summaries[freq_source.get_source_name()] = SummaryTextList(freq_source) util_source = UtilSource() self.graphs[util_source.get_source_name()] = StuiBarGraph(util_source, 'util light', 'util dark', 'util light smooth', 'util dark smooth') self.summaries[util_source.get_source_name()] = SummaryTextList(util_source) temp_source = TemperatureSource(self.custom_temp) alert_colors = ['high temp light', 'high temp dark', 'high temp light smooth', 'high temp dark smooth'] self.graphs[temp_source.get_source_name()] = StuiBarGraph(temp_source, 'temp light', 'temp dark', 'temp light smooth', 'temp dark smooth', alert_colors=alert_colors) self.summaries[temp_source.get_source_name()] = SummaryTextList(temp_source, 'high temp txt') rapl_power_source = RaplPowerSource() self.graphs[rapl_power_source.get_source_name()] = StuiBarGraph(rapl_power_source, 'power dark', 'power light', 'power dark smooth', 'power light smooth') self.summaries[rapl_power_source.get_source_name()] = SummaryTextList(rapl_power_source) # only interested in available graph self.available_graphs = OrderedDict((key, val) for key, val in self.graphs.items() if val.get_is_available()) self.available_summaries = OrderedDict((key, val) for key, val in self.summaries.items() if val.get_is_available()) self.visible_graphs = self.available_graphs.copy() self.show_graphs() cpu_stats = self.cpu_stats() graph_controls = self.graph_controls() graph_stats = self.graph_stats() text_col = ViListBox(urwid.SimpleListWalker(cpu_stats + graph_controls + [urwid.Divider()] + graph_stats)) vline = urwid.AttrWrap(urwid.SolidFill(u'\u2502'), 'line') w = urwid.Columns([ ('fixed', 20, text_col), ('fixed', 1, vline), ('weight', 2, self.graph_place_holder), ], dividechars=1, focus_column=0) w = urwid.Padding(w, ('fixed left', 1), ('fixed right', 0)) w = urwid.AttrWrap(w, 'body') w = urwid.LineBox(w) w = urwid.AttrWrap(w, 'line') self.main_window_w = w return self.main_window_w