Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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())
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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