Example #1
0
class OverviewWidget(QWidget):
    """
    The overviewWidget of the ArniGuiOverview-Plugin.
    """
    
    def __init__(self):
        """
        Initializes the widget.
        """
        super(OverviewWidget, self).__init__()

        # Get path to UI file which is a sibling of this file
        self.rp = rospkg.RosPack()
        ui_file = os.path.join(self.rp.get_path('arni_rqt_overview_plugin'), 'resources', 'OverviewWidget.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self)

        self.__draw_graphs = False

        self.__log_delegate = LogDelegate()
        self.log_tab_tree_view.setItemDelegate(self.__log_delegate)

        self.__last_update = rospy.Time.now()
        
        self.__model = ROSModel()

        self.__log_filter_proxy = LogFilterProxy()

        self.__logger = self.__model.get_logger()
        self.__style_string = ".detailed_data_overview {\n" \
                               "    font-size: 13\n;" \
                               "}\n"

        self.information_tab_text_browser.setStyleSheet(self.__style_string)

        self.range_combo_box.clear()
        #todo: are these in the right order?
        self.range_combo_box.addItem("10 " + self.tr("Seconds"))
        self.range_combo_box.addItem("30 " + self.tr("Seconds"))
        #todo: adapt time!!!
        self.range_combo_box.addItem("60 " + self.tr("Seconds"))
        self.range_combo_box.setCurrentIndex(0)

        self.tab_widget.setTabText(0, self.tr("Information"))
        self.tab_widget.setTabText(1, self.tr("Graphs"))
        self.tab_widget.setTabText(2, self.tr("Log"))

        self.selected_label.setText(self.tr("Selected") + ":")
        self.range_label.setText(self.tr("Range") + ":")


        self.__log_filter_proxy.filter_by_item(None)
        self.__log_filter_proxy.setDynamicSortFilter(True)

        #set proxy model
        self.__log_filter_proxy.setSourceModel(self.__logger.get_representation())

        self.log_tab_tree_view.setModel(self.__log_filter_proxy)
        self.log_tab_tree_view.setRootIsDecorated(True)
        self.log_tab_tree_view.setAlternatingRowColors(True)
        self.log_tab_tree_view.setSortingEnabled(True)
        self.log_tab_tree_view.sortByColumn(1, Qt.AscendingOrder)

        self.__connect_slots()

        self.__state = "ok"
        self.__previous_state = "ok"

        self.__current_range_combo_box_index = 0
        self.__current_selected_combo_box_index = 0
        self.__last_update = rospy.Time.now()

        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.__graph_layout = ResizeableGraphicsLayoutWidget(self.__on_graph_window_size_changed)
        self.graph_scroll_area.setWidget(self.__graph_layout)
        self.__plotable_items = self.__model.get_root_item().get_plotable_items()
        self.__items_per_group = 1
        self.__expected_items_per_group = 1
        self.__number_of_groups = 1

        self.__update_graphs_lock = Lock()
        self.__first_update_pending = True

        self.__graph_dict = {}

        self.__first_resize = True

        self.__plotted_curves = {}
        self.create_graphs()

        self.__timer = Timer(Duration(secs=1.0), self.update_graphs)


    def __del__(self):
        """
        Destructor of the widget.
        """
        self.__draw_graphs = False
        self.__timer.stop()
        del self.__timer

    def create_graphs(self):
        """
        Creates the graphs for the plot.
        """
        self.__update_graphs_lock.acquire()
        first_iteration = True
        first_view = None
        i = 0
        self.__expected_items_per_group = 0
        self.__graph_layout.clear()

        for key in self.__plotable_items[min(self.__current_selected_combo_box_index *
                                            self.__items_per_group, len(self.__plotable_items)):
                                            min((self.__current_selected_combo_box_index + 1)
                                            * self.__items_per_group, len(self.__plotable_items))]:
            plot_widget = None
            if first_iteration:
                first_iteration = False
                date_axis = DateAxis(orientation="bottom")
                first_view = pg.ViewBox()

                plot_widget = self.__graph_layout.addPlot(title=self.tr(key), axisItems={'bottom': date_axis}, viewBox=first_view)
            else:

                date_axis = DateAxis(orientation="bottom")
                view_box = pg.ViewBox()
                plot_widget = self.__graph_layout.addPlot(title=self.tr(key), viewBox=view_box, axisItems={'bottom': date_axis})
                view_box.setXLink(first_view)

            #performance enhancements when only a short range of the plot is shown
            #plot_widget.setClipToView(clip=True)
            plot_widget.setYRange(-1, 1)
            self.__graph_dict[key] = plot_widget
            self.__graph_layout.nextRow()
            plot_widget = self.__graph_dict[key]
            plot_widget.showGrid(x=True, y=True)
            plot_widget.setMenuEnabled(enableMenu=True)
            plot_widget.enableAutoRange('xy', True)
            x = np.array([1])
            y = np.array([int(str(Time.now()))/1000000000])
            self.__plotted_curves[key] = plot_widget.plot(x=x, y=y, fillLevel=0, brush=(50, 50, 200, 100),
                                                          pen=(255, 0, 0))
            self.__expected_items_per_group += 1
        self.__first_update_pending = True
        self.__update_graphs_lock.release()


    def __connect_slots(self):
        """
        Connects the slots.
        """
        self.tab_widget.currentChanged.connect(self.__on_current_tab_changed)
        self.range_combo_box.currentIndexChanged.connect(self.__on_range_combo_box_index_changed)
        self.__model.layoutChanged.connect(self.update)
        self.pause_button.clicked.connect(self.__on_pause_button_clicked)
        self.selected_combo_box.currentIndexChanged.connect(self.__on_selected_combo_box_index_changed)


    def __on_graph_window_size_changed(self):
        # getting the size
        size = self.__graph_layout.size()
        items_per_group = max(int(math.ceil((size.height() - 100) / 200 + 1)), 1)
        if items_per_group is not self.__items_per_group or self.__first_resize:
            self.__first_resize = False
            self.__graph_layout.set_blocked(True)
            self.__items_per_group = 1 if items_per_group < 1 else items_per_group
            self.__number_of_groups = int(math.ceil(len(self.__plotable_items) / float(self.__items_per_group)))
            # change the groups in the widget
            self.selected_combo_box.clear()
            for group in range(0, self.__number_of_groups):
                list = self.__plotable_items[min(group *
                                    self.__items_per_group, len(self.__plotable_items)):min((group + 1)
                                                            * self.__items_per_group, len(self.__plotable_items))]
                content = ""
                for i in range(0, len(list) - 1):
                    content += self.tr(list[i])
                    content += ", "
                content += list[len(list) - 1]
                self.selected_combo_box.addItem(content)
            # redraw
            self.create_graphs()
            self.update_graphs(None)
            self.__graph_layout.set_blocked(False)


    def __on_selected_combo_box_index_changed(self, index):
        """
        Updates what is shown in the graphs

        :param index: the index of the selected range
        :type index: int
        """
        if index is not -1:
            self.__current_selected_combo_box_index = index
            self.create_graphs()
            self.update_graphs(None)


    def __on_pause_button_clicked(self):
        """
        To be called whenever the pause button is clicked. Stops the graphs from updating until the pause button
        is clicked again and the other way.
        """
        if self.__draw_graphs:
            self.__draw_graphs = False
            self.pause_button.setText(self.tr("Continue"))
        else:
            self.__draw_graphs = True
            self.pause_button.setText(self.tr("Pause"))


    def __on_current_tab_changed(self, tab):
        """
        The Plugin wants to get notified when the tab changed so it can e.g. draw the graphs.

        :param tab: the index of the selected tab
        :type tab: int
        """
        if tab is 1:
            if self.pause_button.text() is not "Continue":
                self.__draw_graphs = True
            else:
                self.__draw_graphs = False
        else:
            self.__draw_graphs = False


    def __on_range_combo_box_index_changed(self, index):
        """
        Handels the change of the graph range.

        :param index: the index of the selected range
        :type index: int
        """
        self.__current_range_combo_box_index = index


    def update(self):
        """
        Updates the Plugin and draws the graphs if draw_graphs is true.
        """
        data_dict = self.__model.get_root_item().get_latest_data("state")
        
        self.__state = data_dict["state"]

        if self.__previous_state is not self.__state:
            self.__previous_state = self.__state
            if self.__state == "ok":
                self.status_text_line_edit.setText(self.tr("Current status: Ok"))
                pixmap = QPixmap(os.path.join(self.rp.get_path('arni_rqt_overview_plugin'), 'resources/graphics',
                                              'light_green.png'))
            elif self.__state == "warning":
                self.status_text_line_edit.setText(self.tr("Current status: Warning"))
                pixmap = QPixmap(os.path.join(self.rp.get_path('arni_rqt_overview_plugin'), 'resources/graphics',
                                              'light_orange.png'))
            else:
                self.status_text_line_edit.setText(self.tr("Current status: Error"))
                pixmap = QPixmap(os.path.join(self.rp.get_path('arni_rqt_overview_plugin'), 'resources/graphics',
                                              'light_red.png'))
            self.status_light_label.setPixmap(pixmap)

        if self.information_tab_text_browser:
            scroll_value = self.information_tab_text_browser.verticalScrollBar().value()
            self.information_tab_text_browser.setHtml(self.__model.get_overview_text())
            self.information_tab_text_browser.verticalScrollBar().setSliderPosition(scroll_value)

    def update_graphs(self, event):
        """
        Updates and redraws the graphs.
        """
        self.__update_graphs_lock.acquire()
        if self.__draw_graphs or self.__first_update_pending:

            plotable_items = self.__plotable_items[min(self.__current_selected_combo_box_index *
                                self.__items_per_group, len(self.__plotable_items)):min((self.__current_selected_combo_box_index + 1)
                                                        * self.__items_per_group, len(self.__plotable_items))]
            plotable_data = self.__model.get_root_item().get_items_younger_than(
                Time.now() - (Duration(secs=self.__combo_box_index_to_seconds(self.__current_range_combo_box_index)) if int(Duration(secs=self.__combo_box_index_to_seconds(self.__current_range_combo_box_index)).to_sec()) <= int(Time.now().to_sec()) else Time(0) ),
                "window_stop", *plotable_items)
            temp_time = []
            temp_content = []

            if plotable_data["window_stop"]:
                modulo = (len(plotable_data["window_stop"]) / 200) + 1

                length = len(plotable_data["window_stop"])
            else:
                length = 0
                modulo = 1
            for i in range(0, length, modulo):
                # now having maximally 100 items to plot :)
                temp_time.append(int(str(plotable_data["window_stop"][i]))/1000000000)
            x = np.array(temp_time)


            for key in plotable_items:
                for i in range(0, length, modulo):
                    temp_content.append(plotable_data[key][i])
                y = np.array(temp_content)
                del temp_content[:]

                self.__plotted_curves[key].setData(x=x, y=y)
                
        self.__first_update_pending = False
        self.__update_graphs_lock.release()


    def __combo_box_index_to_seconds(self, index):
        """
        Calculates the range from the combo-box index.
        
        :param index: the index of teh combo-box
        :type index: int
        
        :returns: the seconds of the selected index 
        :rtype: int
        """
        if self.__current_range_combo_box_index == 0:
            return 10
        elif self.__current_range_combo_box_index == 1:
            return 30
        else:
            return 60


    def get_current_tab(self):
        """
        Returns the current tab.
        
        :returns: the current tab 
        :rtype: int
        """
        return self.tab_widget.currentIndex()


    def set_current_tab(self, index=0):
        """
        Sets the default tab.
        
        :param index: the index of the tab
        :type index: int
        """
        if index is None:
            index = 0
        self.tab_widget.setCurrentIndex(index)
        # WARNING: PROBABLY DOUBLE CALL OF __ON_CURRENT_TAB_CHANGED HERE BUT CANNOT BE FIXED SO EASILY
        self.__on_current_tab_changed(index)



    def get_range_combo_box_index(self):
        """
        Returns the index of the combo-box.
        
        :returns: the index 
        :rtype: int
        """
        return self.range_combo_box.currentIndex()


    def set_range_combo_box_index(self, index=0):
        """
        Sets the default value of the combo-box.
        
        :param index: the index of the combo-box
        :type index: int
        """
        if index is None:
            index = 0
        self.range_combo_box.setCurrentIndex(index)
Example #2
0
    def __init__(self):
        """
        Initializes the widget.
        """
        super(OverviewWidget, self).__init__()

        # Get path to UI file which is a sibling of this file
        self.rp = rospkg.RosPack()
        ui_file = os.path.join(self.rp.get_path('arni_rqt_overview_plugin'), 'resources', 'OverviewWidget.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self)

        self.__draw_graphs = False

        self.__log_delegate = LogDelegate()
        self.log_tab_tree_view.setItemDelegate(self.__log_delegate)

        self.__last_update = rospy.Time.now()
        
        self.__model = ROSModel()

        self.__log_filter_proxy = LogFilterProxy()

        self.__logger = self.__model.get_logger()
        self.__style_string = ".detailed_data_overview {\n" \
                               "    font-size: 13\n;" \
                               "}\n"

        self.information_tab_text_browser.setStyleSheet(self.__style_string)

        self.range_combo_box.clear()
        #todo: are these in the right order?
        self.range_combo_box.addItem("10 " + self.tr("Seconds"))
        self.range_combo_box.addItem("30 " + self.tr("Seconds"))
        #todo: adapt time!!!
        self.range_combo_box.addItem("60 " + self.tr("Seconds"))
        self.range_combo_box.setCurrentIndex(0)

        self.tab_widget.setTabText(0, self.tr("Information"))
        self.tab_widget.setTabText(1, self.tr("Graphs"))
        self.tab_widget.setTabText(2, self.tr("Log"))

        self.selected_label.setText(self.tr("Selected") + ":")
        self.range_label.setText(self.tr("Range") + ":")


        self.__log_filter_proxy.filter_by_item(None)
        self.__log_filter_proxy.setDynamicSortFilter(True)

        #set proxy model
        self.__log_filter_proxy.setSourceModel(self.__logger.get_representation())

        self.log_tab_tree_view.setModel(self.__log_filter_proxy)
        self.log_tab_tree_view.setRootIsDecorated(True)
        self.log_tab_tree_view.setAlternatingRowColors(True)
        self.log_tab_tree_view.setSortingEnabled(True)
        self.log_tab_tree_view.sortByColumn(1, Qt.AscendingOrder)

        self.__connect_slots()

        self.__state = "ok"
        self.__previous_state = "ok"

        self.__current_range_combo_box_index = 0
        self.__current_selected_combo_box_index = 0
        self.__last_update = rospy.Time.now()

        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.__graph_layout = ResizeableGraphicsLayoutWidget(self.__on_graph_window_size_changed)
        self.graph_scroll_area.setWidget(self.__graph_layout)
        self.__plotable_items = self.__model.get_root_item().get_plotable_items()
        self.__items_per_group = 1
        self.__expected_items_per_group = 1
        self.__number_of_groups = 1

        self.__update_graphs_lock = Lock()
        self.__first_update_pending = True

        self.__graph_dict = {}

        self.__first_resize = True

        self.__plotted_curves = {}
        self.create_graphs()

        self.__timer = Timer(Duration(secs=1.0), self.update_graphs)
Example #3
0
class SelectionWidget(QWidget):
    """
    The SelectionWidget of the ArniGuiDetail-Plugin.
    """
    
    def __init__(self, model):
        """
        Initializes the Widget.
        
        :param model: the model of the widget
        :type model: ROSModel
        """
        super(SelectionWidget, self).__init__()
        self.setObjectName('selection_widget')
        self.__model = model

        # Get path to UI file which is a sibling of this file
        self.rp = rospkg.RosPack()
        ui_file = os.path.join(self.rp.get_path('arni_rqt_detail_plugin'), 'resources', 'SelectionWidget.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self)
        self.setObjectName('SelectionWidgetUi')

        self.__selected_item = None


        self.__draw_graphs = True
        self.__current_combo_box_index = 0

        self.__last_update = rospy.Time.now()

        try:
            if rospy.get_param("/enable_statistics") == False:
                raise KeyError('/enable_statistics')
        except KeyError:
            self.__overview_widget = None
            raise EnvironmentError("/enable_statistics is either not set or set to false - arni gui would not work correctly. Please make sure to start "
                             "roscore with the neccesary parameters or to load these while running (see init_params.launch)")

        self.__values_dict = {
            "bandwidth_mean": 0,
            "bandwidth_stddev": 0,
            "bandwidth_max": 0,
        }

        self.__logger = self.__model.get_logger()
        self.__log_filter_proxy = LogFilterProxy()       
        self.__log_filter_proxy.filter_by_item(self.__selected_item)
        self.__log_filter_proxy.setDynamicSortFilter(True)        
        self.__log_filter_proxy.setSourceModel(self.__logger.get_representation())
        self.log_tab_tree_view.setModel(self.__log_filter_proxy)
        self.__log_delegate = LogDelegate()
        self.log_tab_tree_view.setItemDelegate(self.__log_delegate)

        self.__style_string = ".detailed_data {\n" \
                               "    font-size: 12\n;" \
                               "}\n"
        self.__style_string = ".erroneous_entry {\n" \
                               "    color: red\n;" \
                               "}\n"

        self.information_tab_text_browser.setStyleSheet(self.__style_string)

        self.range_combo_box.clear()
        self.range_combo_box.addItem("10 " + self.tr("Seconds"))
        self.range_combo_box.addItem("30 " + self.tr("Seconds"))
        self.range_combo_box.addItem("60 " + self.tr("Seconds"))
        self.range_combo_box.setCurrentIndex(0)

        #self.scrollAreaWidgetContents_2.setWidget(self.host_node_label)

        self.tab_widget.setTabText(0, self.tr("Information"))
        self.tab_widget.setTabText(1, self.tr("Graphs"))
        self.tab_widget.setTabText(2, self.tr("Log"))
        self.tab_widget.setTabText(3, self.tr("Actions"))

        self.stop_push_button.setText(self.tr("Stop Node"))
        self.restart_push_button.setText(self.tr("Restart Node"))
        self.stop_push_button.setEnabled(False)
        self.restart_push_button.setEnabled(False)
        
        ### CARSON ADDED ###
        # set default values for throttle rate and window sliders
        self.throttle_rate_slider.setFocusPolicy(Qt.StrongFocus)
        self.throttle_rate_slider.setValue(5000) 
        self.throttle_window_slider.setFocusPolicy(Qt.StrongFocus)
        self.throttle_window_slider.setValue(500)
        
        # set up validator for throttle rate and window text fields 
        # only allows floating point numbers
        regex = QRegExp(r'[0-9]*\.?[0-9]+')
        validator = QRegExpValidator(regex)
        self.throttle_rate.setValidator(validator)
        self.throttle_window.setValidator(validator)
        
        # set up QButtonGroup for message/bandwidth throttle type radio buttons
        self.throttle_radio_group = QButtonGroup()
        self.throttle_radio_group.addButton(self.throttle_message_radio)
        self.throttle_radio_group.addButton(self.throttle_bandwidth_radio)
        self.throttle_radio_group.buttonClicked.connect(self.__on_type_button_clicked)
        
        ### ###
        
        self.selected_label.setText(self.tr("Selected") + ":")
        self.range_label.setText(self.tr("Range") + ":")
        
        self.log_tab_tree_view.setRootIsDecorated(False)
        self.log_tab_tree_view.setAlternatingRowColors(True)
        self.log_tab_tree_view.setSortingEnabled(True)
        self.log_tab_tree_view.sortByColumn(1, Qt.AscendingOrder)

        self.__current_range_combo_box_index = 0
        self.__current_selected_combo_box_index = 0

        self.set_selected_item(self.__selected_item)
        self.__model.layoutChanged.connect(self.update)

        self.__state = "ok"
        self.__previous_state = "ok"

        self.__selected_item_changed = True

        self.__deleted = False
        
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.__graph_layout = ResizeableGraphicsLayoutWidget(self.__on_graph_window_size_changed)
        self.graph_scroll_area.setWidget(self.__graph_layout)
        self.__plotable_items = None#self.__selected_item.get_plotable_items()
        self.__items_per_group = 1
        self.__expected_items_per_group = 1
        self.__number_of_groups = 1

        self.__update_graphs_lock = Lock()
        self.__first_update_pending = True

        self.__graph_dict = {}

        self.__plotted_curves = {}
        #self.create_graphs()

        self.__timer = Timer(Duration(secs=1.0), self.update_graphs)

    def __del__(self):
        self.__deleted = True

    def connect_slots(self):
        """
        Connects the slots.
        """
        # : tab_widget
        self.tab_widget.currentChanged.connect(self.__on_current_tab_changed)
        #: restart_push_button
        self.restart_push_button.clicked.connect(self.__on_restart_push_button_clicked)
        #: stop_push_button
        self.stop_push_button.clicked.connect(self.__on_stop_push_button_clicked)
        #: range_combo_box
        self.range_combo_box.currentIndexChanged.connect(self.__on_range_combo_box_index_changed)
        #pause button
        self.pause_button.clicked.connect(self.__on_pause_button_clicked)
        # selected combo box
        self.selected_combo_box.currentIndexChanged.connect(self.__on_selected_combo_box_index_changed)
        
        ### CARSON ADDED ###
        # connect sliders to text fields and update text fields for first time
        self.throttle_rate_slider.valueChanged.connect(self.__on_throttle_rate_slider_changed)
        self.throttle_window_slider.valueChanged.connect(self.__on_throttle_window_slider_changed)
        self.__on_throttle_rate_slider_changed(self.throttle_rate_slider.value())
        self.__on_throttle_window_slider_changed(self.throttle_window_slider.value())
        
        # connect text fields to sliders
        self.throttle_rate.editingFinished.connect(self.__on_throttle_rate_changed)
        self.throttle_window.editingFinished.connect(self.__on_throttle_window_changed)
        
        # connect buttons to actions
        self.throttle_start_button.clicked.connect(self.__on_throttle_start_button_clicked)
        self.throttle_stop_button.clicked.connect(self.__on_throttle_stop_button_clicked)
        self.throttle_reset_button.clicked.connect(self.__on_throttle_reset_button_clicked)
        ### ###
        
    ### CARSON ADDED ###
    def __on_throttle_rate_slider_changed(self, value):
        """Called whenever throttle rate slider changes value.
        Updates the throttle rate text field to match the slider value.
        Performs conversion if necessary.

        Args:
            value (int): new value of throttle rate slider
        """
        if self.throttle_radio_group.checkedButton() is self.throttle_message_radio:
            value = convert_from_slider(value, THROTTLE_RATE_SLIDER_DPI)
        self.throttle_rate.setText(str(value))
    
    def __on_throttle_rate_changed(self):
        """Called whenever throttle rate text field emits the "finishedEditing" signal.
        Updates the throttle rate slider to match the throttle rate text field, using
        necessary conversions and checking for endpoints.
        """
        text = self.throttle_rate.text()
        value = float(text)
        if self.throttle_radio_group.checkedButton() is self.throttle_message_radio:
            value = convert_to_slider(value, THROTTLE_RATE_SLIDER_DPI)
            if value%1 != 0:
                value = int(value)
        else:
            value = int(value)
        # check for endpoints
        if value > self.throttle_rate_slider.maximum():
            value = self.throttle_rate_slider.maximum()
        if value < self.throttle_rate_slider.minimum():
            value = self.throttle_rate_slider.minimum()
        # call slider update method manually if value is same (keeps text field in sync)
        if self.throttle_rate_slider.value() == value:
            self.__on_throttle_rate_slider_changed(value)
        self.throttle_rate_slider.setValue(value)
        
    def __on_throttle_window_slider_changed(self, value):
        """Called whenever throttle window slider changes value.
        Updates the throttle window text field to match the slider value
        using the proper conversion.

        Args:
            value (int): new value of throttle window slider
        """
        self.throttle_window.setText(str(convert_from_slider(value, THROTTLE_WINDOW_SLIDER_DPI)))
    
    def __on_throttle_window_changed(self):
        """Called whenever throttle window text field emits the "finishedEditing" signal.
        Updates the throttle window slider to match the throttle window text field, using
        necessary conversions and checking for endpoints.
        """
        text = self.throttle_window.text()
        value = convert_to_slider(float(text), THROTTLE_WINDOW_SLIDER_DPI)
        # check for endpoints
        if value > self.throttle_window_slider.maximum():
            value = self.throttle_window_slider.maximum()
        if value < self.throttle_window_slider.minimum():
            value = self.throttle_window_slider.minimum()
        # call slider update method manually if value is same (keeps text field in sync)
        if self.throttle_window_slider.value() == value:
            self.__on_throttle_window_slider_changed(value)
        self.throttle_window_slider.setValue(value)

    def __on_type_button_clicked(self, button):
        """Called whenever a throttle type radio button is clicked.
        Performs the necessary GUI updates for the new throttle type.
        
        Args:
            button (QRadioButton): currently checked radio button.
        """
        throttle = self.__selected_item.topic_item.throttle
        if button is self.throttle_message_radio:
            self.throttle_rate_label.setText('Rate (Hz)')
            self.__update_throttle_window_gui(False)
            self.throttle_rate_slider.setMaximum(convert_to_slider(1000, THROTTLE_RATE_SLIDER_DPI))    
            self.throttle_rate_slider.setTickInterval(convert_to_slider(100, THROTTLE_RATE_SLIDER_DPI))    
            value = 0
            if throttle is None or not self.typeButtonMatchesThrottleType(throttle):
                value = convert_to_slider(500, THROTTLE_RATE_SLIDER_DPI)
            else:
                value = convert_to_slider(throttle.rate, THROTTLE_RATE_SLIDER_DPI)
            self.throttle_rate_slider.setValue(value)
            self.throttle_rate.setMaxLength(5)
        else:
            self.throttle_rate_label.setText('Rate (Kb/s)')
            self.__update_throttle_window_gui(True)
            self.throttle_rate_slider.setMaximum(1e6)    
            self.throttle_rate_slider.setTickInterval(1e5)    
            value = 0
            if throttle is None or not self.typeButtonMatchesThrottleType(throttle):
                value = 5e5
            else:
                value = throttle.bandwidth
            self.throttle_rate_slider.setValue(value)
            self.throttle_rate.setMaxLength(7)
            self.throttle_window_slider.setValue(convert_to_slider(5, THROTTLE_WINDOW_SLIDER_DPI))
            
    def __on_throttle_start_button_clicked(self):
        """Called whenever the Start Throttle button is clicked.

        Starts or updates the throttle as necessary according to which radio button
        is active (message or bandwidth)
        """
        # grab topic name and inner topic item from selected_item
        # this is necessary because only the TopicItem class has the new throttle attribute
        topic_name = self.__selected_item.seuid.split('/')[-1]
        topic_item = self.__selected_item.topic_item
        # convert rate field to number 
        throttle_rate = float(self.throttle_rate.text())            
        
        # determine if we need to make a new throttle or update an existing one
        if topic_item.throttle is None or not self.typeButtonMatchesThrottleType(topic_item.throttle):
            if topic_item.throttle is not None:
                # stop existing throttle if there is one
                print(topic_item.throttle.stop())
            if self.throttle_radio_group.checkedButton() is self.throttle_message_radio:
                topic_item.throttle = MessageThrottle(topic_name, topic_name + '_message_throttled', throttle_rate)
                # self.throttle_message_radio.setPalette(self.active_label_palette)
                print(topic_item.throttle.start())
                print('started message throttler')
            else:
                # addtionally grab window value for a bandwidth throttle
                throttle_window = float(self.throttle_window.text())
                topic_item.throttle = BandwidthThrottle(topic_name, topic_name + '_bandwidth_throttled', kb_to_bytes(throttle_rate), throttle_window)
                # self.throttle_window_radio.setPalette(self.active_label_palette)
                print(topic_item.throttle.start())
                print('started bandwidth throttler')
            # enable stop button now that a throttle is active
            self.throttle_stop_button.setEnabled(True)
        else:
            if self.throttle_radio_group.checkedButton() is self.throttle_message_radio:
                if throttle_rate != topic_item.throttle.rate:
                    success = topic_item.throttle.update(rate=throttle_rate)
                    print(success)
                    if success == None:
                        print('no running throttle')
                else:
                    print('no updates to throttle necessary')
            else:
                throttle_window = float(self.throttle_window.text())
                if throttle_rate != topic_item.throttle.bandwidth or throttle_window != topic_item.throttle.window:
                    success = topic_item.throttle.update(bandwidth=throttle_rate, window=throttle_window)
                    print(success)
                    if success == None:
                        print('no running throttle')
                else:
                    print('no updates to throttle necessary')
                

    def __on_throttle_stop_button_clicked(self):
        """Called whenever the Stop Throttle button is clicked.
        Stops the running throttle, resets the topic's throttle attribute, and disables
        the Stop Throttle button.
        """
        print(self.__selected_item.topic_item.throttle.stop())
        self.__selected_item.topic_item.throttle = None
        self.throttle_stop_button.setEnabled(False)
        
    def __on_throttle_reset_button_clicked(self):
        """Called whenever the Reset Throttle button is clicked.
        Resets the throttle parameters to current throttle values or defaults if no
        throttle is running.
        """
        throttle = self.__selected_item.topic_item.throttle
        if throttle is None or not self.typeButtonMatchesThrottleType(throttle):
            self.__on_type_button_clicked(self.throttle_radio_group.checkedButton())
        else:
            if self.throttle_radio_group.checkedButton() is self.throttle_message_radio:
                self.throttle_rate_slider.setValue(convert_to_slider(throttle.rate, THROTTLE_RATE_SLIDER_DPI))
            else:
                self.throttle_rate_slider.setValue(bytes_to_kb(throttle.bandwidth))
                self.throttle_window_slider.setValue(convert_to_slider(throttle.window, THROTTLE_WINDOW_SLIDER_DPI))

    def typeButtonMatchesThrottleType(self, throttle):
        """Determines if the active type radio button matches the type of the
        provided throttle.

        Args:
            throttle (rosthrottle.MessageThrottle or rosthrottle.BandwidthThrottle): throttle to compare with
        """
        message_match = self.throttle_radio_group.checkedButton() is self.throttle_message_radio and isinstance(throttle, MessageThrottle)
        bandwidth_match = self.throttle_radio_group.checkedButton() is self.throttle_bandwidth_radio and isinstance(throttle, BandwidthThrottle)
        return message_match or bandwidth_match


    def __update_throttle_window_gui(self, mode):
        """Updates the throttle window GUI components to the given mode.
        
        Args:
            mode (bool): true if enabling throttle window GUI components, false if disabling
        """
        self.throttle_window_label.setEnabled(mode)
        self.throttle_window_slider.setEnabled(mode)
        self.throttle_window.setEnabled(mode)

    def __update_throttle_gui(self, mode):
        """Updates the throttle GUI to the given mode.
        
        Args:
            mode (bool): true if enabling throttle GUI components, false if disabling
        """
        if self.throttle_radio_group.checkedButton() is self.throttle_bandwidth_radio:
            self.__update_throttle_window_gui(mode)
        self.throttle_rate_slider.setEnabled(mode)
        if self.__selected_item.can_execute_throttles():
            if self.__selected_item.topic_item.throttle is not None:
                self.throttle_stop_button.setEnabled(True)
                self.__update_throttle_params(throttle=self.__selected_item.topic_item.throttle)
            else:
                self.throttle_stop_button.setEnabled(False)
                self.__update_throttle_params()
        else:
            self.throttle_stop_button.setEnabled(mode)
        self.throttle_start_button.setEnabled(mode)
        self.throttle_rate_label.setEnabled(mode)
        self.throttle_bandwidth_radio.setEnabled(mode)
        self.throttle_message_radio.setEnabled(mode)
        self.throttle_rate.setEnabled(mode)
        self.throttle_reset_button.setEnabled(mode)
        
    def __update_throttle_params(self, throttle=None):
        """Updates the throttle parameters based on the given throttle.

        Args:
            throttle (optional, rosthrottle.MessageThrottle or rosthrottle.BandwidthThrottle): throttle
                to use as source of throttle parameters. If not provided, default values are used.
        """
        if throttle is None:
            self.throttle_message_radio.setChecked(True)
            self.__on_type_button_clicked(self.throttle_message_radio)
        else:
            if isinstance(throttle, MessageThrottle):
                self.throttle_message_radio.setChecked(True)
                self.__on_type_button_clicked(self.throttle_message_radio)
                self.throttle_rate_slider.setValue(convert_to_slider(throttle.rate, THROTTLE_RATE_SLIDER_DPI))
                self.throttle_window_slider.setValue(500)
            else:
                self.throttle_bandwidth_radio.setChecked(True)
                self.__on_type_button_clicked(self.throttle_bandwidth_radio)
                self.throttle_rate_slider.setValue(bytes_to_kb(throttle.bandwidth))
                self.throttle_window_slider.setValue(convert_to_slider(throttle.window, THROTTLE_WINDOW_SLIDER_DPI))
    ### ###

    def create_graphs(self):
        """
        Creates the graphs for the plot.
        """
        self.__update_graphs_lock.acquire()
        if self.__selected_item is not None:
            first_iteration = True
            first_view = None
            i = 0
            self.__expected_items_per_group = 0
            self.__graph_layout.clear()

            if len(self.__plotable_items) is 0:
                raise UserWarning()
            for key in self.__plotable_items[min(self.__current_selected_combo_box_index *
                                                self.__items_per_group, len(self.__plotable_items)):
                                                min((self.__current_selected_combo_box_index + 1)
                                                * self.__items_per_group, len(self.__plotable_items))]:
                plot_widget = None
                if first_iteration:
                    first_iteration = False
                    date_axis = DateAxis(orientation="bottom")
                    first_view = pg.ViewBox()

                    plot_widget = self.__graph_layout.addPlot(title=self.tr(key), axisItems={'bottom': date_axis}, viewBox=first_view)
                else:

                    date_axis = DateAxis(orientation="bottom")
                    view_box = pg.ViewBox()
                    plot_widget = self.__graph_layout.addPlot(title=self.tr(key), viewBox=view_box, axisItems={'bottom': date_axis})
                    view_box.setXLink(first_view)

                #performance enhancements when only a short range of the plot is shown
                #plot_widget.setClipToView(clip=True)
                plot_widget.setYRange(-1, 1)
                self.__graph_dict[key] = plot_widget
                self.__graph_layout.nextRow()
                plot_widget = self.__graph_dict[key]
                plot_widget.showGrid(x=True, y=True)
                plot_widget.setMenuEnabled(enableMenu=True)
                plot_widget.enableAutoRange('xy', True)
                x = np.array([1])
                y = np.array([int(str(Time.now()))/1000000000])
                self.__plotted_curves[key] = plot_widget.plot(x=x, y=y, fillLevel=0, brush=(50, 50, 200, 100),
                                                              pen=(255, 0, 0))
                self.__expected_items_per_group += 1
            self.__first_update_pending = True
        self.__update_graphs_lock.release()


    def __on_graph_window_size_changed(self):
        # getting the size
        if self.__selected_item is not None:
            size = self.__graph_layout.size()
            items_per_group = max(int(math.ceil((size.height() - 100) / 200 + 1)), 1)
            if items_per_group is not self.__items_per_group or self.__selected_item_changed:
                self.__graph_layout.set_blocked(True)
                self.__items_per_group = items_per_group
                self.__number_of_groups = int(math.ceil(len(self.__plotable_items) / float(self.__items_per_group)))
                # change the groups in the widget
                self.selected_combo_box.clear()
                for group in range(0, self.__number_of_groups):
                    list = self.__plotable_items[min(group *
                                        self.__items_per_group, len(self.__plotable_items)):min((group + 1)
                                                                * self.__items_per_group, len(self.__plotable_items))]
                    content = ""
                    for i in range(0, len(list) - 1):
                        content += self.tr(list[i])
                        content += ", "
                    content += list[len(list) - 1]
                    self.selected_combo_box.addItem(content)
                # redraw
                self.create_graphs()
                self.update_graphs(None)
                self.__graph_layout.set_blocked(False)

    def __on_selected_combo_box_index_changed(self, index):
        """
        Updates what is shown in the graphs

        :param index: the index of the selected range
        :type index: int
        """
        if index is not -1:
            self.__current_selected_combo_box_index = index
            self.create_graphs()
            self.update_graphs(None)


    def __on_pause_button_clicked(self):
        """
        To be called whenever the pause button is clicked. Stops the graphs from updating until the pause button
        is clicked again and the other way.
        """
        if self.__draw_graphs:
            self.__draw_graphs = False
            self.pause_button.setText(self.tr("Continue"))
        else:
            self.__draw_graphs = True
            self.pause_button.setText(self.tr("Pause"))


    def set_selected_item(self, index):
        """
        Sets the selected item.

        :param index: the index of the selected item
        :type selected_item: QModelIndex
        """
        if index is not None:
            self.__update_graphs_lock.acquire()
            src_index = index.model().mapToSource(index)
            self.__selected_item = src_index.internalPointer()
            self.__log_filter_proxy.filter_by_item(self.__selected_item)
            if self.__selected_item is not None:
                self.__plotable_items = self.__selected_item.get_plotable_items()
                for key in self.__selected_item.get_list_items():
                    self.__plotable_items.remove(key)
                # check if actions can be executed
                if self.__selected_item.can_execute_actions():
                    self.stop_push_button.setEnabled(True)
                    self.restart_push_button.setEnabled(True)
                else:
                    self.stop_push_button.setEnabled(False)
                    self.restart_push_button.setEnabled(False)
                # check if throttles can be executed
                if self.__selected_item.can_execute_throttles():
                    self.__update_throttle_gui(True)
                else:
                    self.__update_throttle_gui(False)
                self.__selected_item_changed = True
            self.__update_graphs_lock.release()
            self.update()
            self.__on_graph_window_size_changed()


    def __on_current_tab_changed(self, tab):
        """
        Will be called when switching between tabs.

        :param tab: index of the current tab
        :type tab: int
        """
        if tab is 1:
            self.__draw_graphs = True
        else:
            self.__draw_graphs = False


    def __on_restart_push_button_clicked(self):
        """
        Handels the restart button and restarts a host or node.
        """
        if self.__selected_item is not None:
            self.__selected_item.execute_action("restart")


    def __on_stop_push_button_clicked(self):
        """Handels the stop button and stops a host or node."""
        if self.__selected_item is not None:
            self.__selected_item.execute_action("stop")


    def __on_range_combo_box_index_changed(self, index):
        """
        Handels the change of the graph range.

        :param index: the index of the selected range
        :type index: int
        """
        self.__current_combo_box_index = index


    def update_graphs(self, event):
        """
        Updates and redraws the graphs.
        """
        self.__update_graphs_lock.acquire()
        if self.__selected_item is not None:
            if self.__draw_graphs or self.__first_update_pending:
                #print("items per group: " + str(self.__items_per_group))
                #print("combo index: " + str(self.__current_selected_combo_box_index))
                #print("len plot " + str(len(self.__plotable_items)))
                plotable_items = self.__plotable_items[min(self.__current_selected_combo_box_index *
                                    self.__items_per_group, len(self.__plotable_items)):min((self.__current_selected_combo_box_index + 1)
                                                            * self.__items_per_group, len(self.__plotable_items))]
                plotable_data = self.__selected_item.get_items_younger_than(
                    #Time.now() - Duration(secs=self.__combo_box_index_to_seconds(self.__current_range_combo_box_index)),
                    Time.now() - (Duration(secs=(self.__combo_box_index_to_seconds(self.__current_range_combo_box_index) + 10 )) if int(Duration(secs=self.__combo_box_index_to_seconds(self.__current_range_combo_box_index)).to_sec()) <= int(Time.now().to_sec()) else Time(0) ),
                    "window_stop", *plotable_items)
                if "window_stop" in plotable_data:
                    if plotable_data["window_stop"]:
                        temp_time = []
                        temp_content = []

                        length = len(plotable_data["window_stop"])
                        modulo = (length / 200) + 1

                        for i in range(0, length, modulo):
                            # now having maximally 100 items to plot :)
                            temp_time.append(plotable_data["window_stop"][i].to_sec())
                        x = np.array(temp_time)

                        list_entries = self.__selected_item.get_list_items()
                        time_entries = self.__selected_item.get_time_items()

                        for key in plotable_items:
                            if key in list_entries:
                                pass
                            else:
                                if key in time_entries:
                                    for i in range(0, length, modulo):
                                        temp_content.append(float(str(plotable_data[key][i]))/1000000000)
                                else:
                                    for i in range(0, length, modulo):
                                        temp_content.append(plotable_data[key][i])
                                y = np.array(temp_content)
                                del temp_content[:]
                                self.__plotted_curves[key].setData(x=x, y=y)
                    else:
                        pass

            self.__first_update_pending = False
        self.__update_graphs_lock.release()
      
    
    def update(self):
        """
        Updates the widget.
        """
        if not self.__deleted:
            if self.__selected_item is not None:
                data_dict = self.__selected_item.get_latest_data()
                self.__state = data_dict["state"]
                self.host_node_label.setText(self.tr(self.__selected_item.get_seuid()))

                if self.__previous_state is not self.__state:
                    self.__previous_state = self.__state
                    if self.__state == "ok":
                        self.current_status_label.setText(self.tr("ok"))
                        #self.host_node_label.setText(self.tr("Current Status: Ok"))
                        pixmap = QPixmap(os.path.join(self.rp.get_path('arni_rqt_detail_plugin'), 'resources/graphics',
                                                      'block_green.png'))
                    elif self.__state == "warning":
                        self.current_status_label.setText(self.tr("warning"))
                        #self.host_node_label.setText(self.tr("Current Status: Warning"))
                        pixmap = QPixmap(os.path.join(self.rp.get_path('arni_rqt_detail_plugin'), 'resources/graphics',
                                                      'block_orange.png'))
                    elif self.__state == "unknown":
                        self.current_status_label.setText(self.tr("unkown"))
                        #self.host_node_label.setText(self.tr("Current Status: Unkown"))
                        pixmap = QPixmap(os.path.join(self.rp.get_path('arni_rqt_detail_plugin'), 'resources/graphics',
                                                      'block_grey.png'))
                    else: # error or offline
                        self.current_status_label.setText(self.tr(self.__state))
                        pixmap = QPixmap(os.path.join(self.rp.get_path('arni_rqt_detail_plugin'), 'resources/graphics',
                                                      'block_red.png'))
                    self.status_light_label.setPixmap(pixmap)
                content = self.__selected_item.get_detailed_data()

                scroll_value = self.information_tab_text_browser.verticalScrollBar().value()
                self.information_tab_text_browser.setHtml(content)
                self.information_tab_text_browser.verticalScrollBar().setSliderPosition(scroll_value)
            else:
                self.host_node_label.setText(self.tr("No item selected"))
                self.current_status_label.setText(self.tr("Offline"))
                self.information_tab_text_browser.setText(self.tr("Please select an item in the TreeView to get more information"
                                                          " about it"))


    def __combo_box_index_to_seconds(self, index):
        """
        Calculates the range from the combo-box index.
        
        :param index: the index of teh combo-box
        :type index: int
        
        :returns: the seconds of the selected index 
        :rtype: int
        """
        if self.__current_combo_box_index == 0:
            return 10
        elif self.__current_combo_box_index == 1:
            return 30
        else:
            return 60


    def get_current_tab(self):
        """
        Returns the current tab.
        
        :returns: the current tab 
        :rtype: int
        """
        return self.tab_widget.currentIndex()


    def set_current_tab(self, index=0):
        """
        Sets the default tab.
        
        :param index: the index of the tab
        :type index: int
        """
        if index is None:
            index = 0
        self.tab_widget.setCurrentIndex(index)


    def get_range_combo_box_index(self):
        """
        Returns the index of the combo-box.
        
        :returns: the index
        :rtype: int
        """
        return self.range_combo_box.currentIndex()


    def set_range_combo_box_index(self, index=0):
        """
        Sets the default value of the combo-box.
        
        :param index: the index of the combo-box
        :type index: int
        """
        if index is None:
            index = 0
        self.range_combo_box.setCurrentIndex(index)
Example #4
0
    def __init__(self, model):
        """
        Initializes the Widget.
        
        :param model: the model of the widget
        :type model: ROSModel
        """
        super(SelectionWidget, self).__init__()
        self.setObjectName('selection_widget')
        self.__model = model

        # Get path to UI file which is a sibling of this file
        self.rp = rospkg.RosPack()
        ui_file = os.path.join(self.rp.get_path('arni_rqt_detail_plugin'), 'resources', 'SelectionWidget.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self)
        self.setObjectName('SelectionWidgetUi')

        self.__selected_item = None


        self.__draw_graphs = True
        self.__current_combo_box_index = 0

        self.__last_update = rospy.Time.now()

        try:
            if rospy.get_param("/enable_statistics") == False:
                raise KeyError('/enable_statistics')
        except KeyError:
            self.__overview_widget = None
            raise EnvironmentError("/enable_statistics is either not set or set to false - arni gui would not work correctly. Please make sure to start "
                             "roscore with the neccesary parameters or to load these while running (see init_params.launch)")

        self.__values_dict = {
            "bandwidth_mean": 0,
            "bandwidth_stddev": 0,
            "bandwidth_max": 0,
        }

        self.__logger = self.__model.get_logger()
        self.__log_filter_proxy = LogFilterProxy()       
        self.__log_filter_proxy.filter_by_item(self.__selected_item)
        self.__log_filter_proxy.setDynamicSortFilter(True)        
        self.__log_filter_proxy.setSourceModel(self.__logger.get_representation())
        self.log_tab_tree_view.setModel(self.__log_filter_proxy)
        self.__log_delegate = LogDelegate()
        self.log_tab_tree_view.setItemDelegate(self.__log_delegate)

        self.__style_string = ".detailed_data {\n" \
                               "    font-size: 12\n;" \
                               "}\n"
        self.__style_string = ".erroneous_entry {\n" \
                               "    color: red\n;" \
                               "}\n"

        self.information_tab_text_browser.setStyleSheet(self.__style_string)

        self.range_combo_box.clear()
        self.range_combo_box.addItem("10 " + self.tr("Seconds"))
        self.range_combo_box.addItem("30 " + self.tr("Seconds"))
        self.range_combo_box.addItem("60 " + self.tr("Seconds"))
        self.range_combo_box.setCurrentIndex(0)

        #self.scrollAreaWidgetContents_2.setWidget(self.host_node_label)

        self.tab_widget.setTabText(0, self.tr("Information"))
        self.tab_widget.setTabText(1, self.tr("Graphs"))
        self.tab_widget.setTabText(2, self.tr("Log"))
        self.tab_widget.setTabText(3, self.tr("Actions"))

        self.stop_push_button.setText(self.tr("Stop Node"))
        self.restart_push_button.setText(self.tr("Restart Node"))
        self.stop_push_button.setEnabled(False)
        self.restart_push_button.setEnabled(False)
        
        ### CARSON ADDED ###
        # set default values for throttle rate and window sliders
        self.throttle_rate_slider.setFocusPolicy(Qt.StrongFocus)
        self.throttle_rate_slider.setValue(5000) 
        self.throttle_window_slider.setFocusPolicy(Qt.StrongFocus)
        self.throttle_window_slider.setValue(500)
        
        # set up validator for throttle rate and window text fields 
        # only allows floating point numbers
        regex = QRegExp(r'[0-9]*\.?[0-9]+')
        validator = QRegExpValidator(regex)
        self.throttle_rate.setValidator(validator)
        self.throttle_window.setValidator(validator)
        
        # set up QButtonGroup for message/bandwidth throttle type radio buttons
        self.throttle_radio_group = QButtonGroup()
        self.throttle_radio_group.addButton(self.throttle_message_radio)
        self.throttle_radio_group.addButton(self.throttle_bandwidth_radio)
        self.throttle_radio_group.buttonClicked.connect(self.__on_type_button_clicked)
        
        ### ###
        
        self.selected_label.setText(self.tr("Selected") + ":")
        self.range_label.setText(self.tr("Range") + ":")
        
        self.log_tab_tree_view.setRootIsDecorated(False)
        self.log_tab_tree_view.setAlternatingRowColors(True)
        self.log_tab_tree_view.setSortingEnabled(True)
        self.log_tab_tree_view.sortByColumn(1, Qt.AscendingOrder)

        self.__current_range_combo_box_index = 0
        self.__current_selected_combo_box_index = 0

        self.set_selected_item(self.__selected_item)
        self.__model.layoutChanged.connect(self.update)

        self.__state = "ok"
        self.__previous_state = "ok"

        self.__selected_item_changed = True

        self.__deleted = False
        
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.__graph_layout = ResizeableGraphicsLayoutWidget(self.__on_graph_window_size_changed)
        self.graph_scroll_area.setWidget(self.__graph_layout)
        self.__plotable_items = None#self.__selected_item.get_plotable_items()
        self.__items_per_group = 1
        self.__expected_items_per_group = 1
        self.__number_of_groups = 1

        self.__update_graphs_lock = Lock()
        self.__first_update_pending = True

        self.__graph_dict = {}

        self.__plotted_curves = {}
        #self.create_graphs()

        self.__timer = Timer(Duration(secs=1.0), self.update_graphs)
    def __init__(self, model):
        """
        Initializes the Widget.
        
        :param model: the model of the widget
        :type model: ROSModel
        """
        super(SelectionWidget, self).__init__()
        self.setObjectName('selection_widget')
        self.__model = model

        # Get path to UI file which is a sibling of this file
        self.rp = rospkg.RosPack()
        ui_file = os.path.join(self.rp.get_path('rqt_arni_gui_detail'), 'resources', 'SelectionWidget.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self)
        self.setObjectName('SelectionWidgetUi')

        self.__selected_item = None


        self.__draw_graphs = True
        self.__current_combo_box_index = 0

        self.__last_update = rospy.Time.now()

        try:
            if rospy.get_param("/enable_statistics") == False:
                raise KeyError('/enable_statistics')
        except KeyError:
            self.__overview_widget = None
            raise EnvironmentError("/enable_statistics is either not set or set to false - arni gui would not work correctly. Please make sure to start "
                             "roscore with the neccesary parameters or to load these while running (see init_params.launch)")

        self.__values_dict = {
            "bandwidth_mean": 0,
            "bandwidth_stddev": 0,
            "bandwidth_max": 0,
        }

        self.__logger = self.__model.get_logger()
        self.__log_filter_proxy = LogFilterProxy()       
        self.__log_filter_proxy.filter_by_item(self.__selected_item)
        self.__log_filter_proxy.setDynamicSortFilter(True)        
        self.__log_filter_proxy.setSourceModel(self.__logger.get_representation())
        self.log_tab_tree_view.setModel(self.__log_filter_proxy)
        self.__log_delegate = LogDelegate()
        self.log_tab_tree_view.setItemDelegate(self.__log_delegate)

        self.__style_string = ".detailed_data {\n" \
                               "    font-size: 12\n;" \
                               "}\n"
        self.__style_string = ".erroneous_entry {\n" \
                               "    color: red\n;" \
                               "}\n"

        self.information_tab_text_browser.setStyleSheet(self.__style_string)

        self.range_combo_box.clear()
        self.range_combo_box.addItem("10 " + self.tr("Seconds"))
        self.range_combo_box.addItem("30 " + self.tr("Seconds"))
        self.range_combo_box.addItem("60 " + self.tr("Seconds"))
        self.range_combo_box.setCurrentIndex(0)

        #self.scrollAreaWidgetContents_2.setWidget(self.host_node_label)

        self.tab_widget.setTabText(0, self.tr("Information"))
        self.tab_widget.setTabText(1, self.tr("Graphs"))
        self.tab_widget.setTabText(2, self.tr("Log"))
        self.tab_widget.setTabText(3, self.tr("Actions"))

        self.stop_push_button.setText(self.tr("Stop Node"))
        self.restart_push_button.setText(self.tr("Restart Node"))
        self.stop_push_button.setEnabled(False)
        self.restart_push_button.setEnabled(False)

        self.selected_label.setText(self.tr("Selected") + ":")
        self.range_label.setText(self.tr("Range") + ":")
        
        self.log_tab_tree_view.setRootIsDecorated(False)
        self.log_tab_tree_view.setAlternatingRowColors(True)
        self.log_tab_tree_view.setSortingEnabled(True)
        self.log_tab_tree_view.sortByColumn(1, Qt.AscendingOrder)

        self.__current_range_combo_box_index = 0
        self.__current_selected_combo_box_index = 0

        self.set_selected_item(self.__selected_item)
        self.__model.layoutChanged.connect(self.update)

        self.__state = "ok"
        self.__previous_state = "ok"

        self.__selected_item_changed = True

        self.__deleted = False
        
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.__graph_layout = ResizeableGraphicsLayoutWidget(self.__on_graph_window_size_changed)
        self.graph_scroll_area.setWidget(self.__graph_layout)
        self.__plotable_items = None#self.__selected_item.get_plotable_items()
        self.__items_per_group = 1
        self.__expected_items_per_group = 1
        self.__number_of_groups = 1

        self.__update_graphs_lock = Lock()
        self.__first_update_pending = True

        self.__graph_dict = {}

        self.__plotted_curves = {}
        #self.create_graphs()

        self.__timer = Timer(Duration(secs=1.0), self.update_graphs)
class SelectionWidget(QWidget):
    """
    The SelectionWidget of the ArniGuiDetail-Plugin.
    """
    
    def __init__(self, model):
        """
        Initializes the Widget.
        
        :param model: the model of the widget
        :type model: ROSModel
        """
        super(SelectionWidget, self).__init__()
        self.setObjectName('selection_widget')
        self.__model = model

        # Get path to UI file which is a sibling of this file
        self.rp = rospkg.RosPack()
        ui_file = os.path.join(self.rp.get_path('rqt_arni_gui_detail'), 'resources', 'SelectionWidget.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self)
        self.setObjectName('SelectionWidgetUi')

        self.__selected_item = None


        self.__draw_graphs = True
        self.__current_combo_box_index = 0

        self.__last_update = rospy.Time.now()

        try:
            if rospy.get_param("/enable_statistics") == False:
                raise KeyError('/enable_statistics')
        except KeyError:
            self.__overview_widget = None
            raise EnvironmentError("/enable_statistics is either not set or set to false - arni gui would not work correctly. Please make sure to start "
                             "roscore with the neccesary parameters or to load these while running (see init_params.launch)")

        self.__values_dict = {
            "bandwidth_mean": 0,
            "bandwidth_stddev": 0,
            "bandwidth_max": 0,
        }

        self.__logger = self.__model.get_logger()
        self.__log_filter_proxy = LogFilterProxy()       
        self.__log_filter_proxy.filter_by_item(self.__selected_item)
        self.__log_filter_proxy.setDynamicSortFilter(True)        
        self.__log_filter_proxy.setSourceModel(self.__logger.get_representation())
        self.log_tab_tree_view.setModel(self.__log_filter_proxy)
        self.__log_delegate = LogDelegate()
        self.log_tab_tree_view.setItemDelegate(self.__log_delegate)

        self.__style_string = ".detailed_data {\n" \
                               "    font-size: 12\n;" \
                               "}\n"
        self.__style_string = ".erroneous_entry {\n" \
                               "    color: red\n;" \
                               "}\n"

        self.information_tab_text_browser.setStyleSheet(self.__style_string)

        self.range_combo_box.clear()
        self.range_combo_box.addItem("10 " + self.tr("Seconds"))
        self.range_combo_box.addItem("30 " + self.tr("Seconds"))
        self.range_combo_box.addItem("60 " + self.tr("Seconds"))
        self.range_combo_box.setCurrentIndex(0)

        #self.scrollAreaWidgetContents_2.setWidget(self.host_node_label)

        self.tab_widget.setTabText(0, self.tr("Information"))
        self.tab_widget.setTabText(1, self.tr("Graphs"))
        self.tab_widget.setTabText(2, self.tr("Log"))
        self.tab_widget.setTabText(3, self.tr("Actions"))

        self.stop_push_button.setText(self.tr("Stop Node"))
        self.restart_push_button.setText(self.tr("Restart Node"))
        self.stop_push_button.setEnabled(False)
        self.restart_push_button.setEnabled(False)

        self.selected_label.setText(self.tr("Selected") + ":")
        self.range_label.setText(self.tr("Range") + ":")
        
        self.log_tab_tree_view.setRootIsDecorated(False)
        self.log_tab_tree_view.setAlternatingRowColors(True)
        self.log_tab_tree_view.setSortingEnabled(True)
        self.log_tab_tree_view.sortByColumn(1, Qt.AscendingOrder)

        self.__current_range_combo_box_index = 0
        self.__current_selected_combo_box_index = 0

        self.set_selected_item(self.__selected_item)
        self.__model.layoutChanged.connect(self.update)

        self.__state = "ok"
        self.__previous_state = "ok"

        self.__selected_item_changed = True

        self.__deleted = False
        
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.__graph_layout = ResizeableGraphicsLayoutWidget(self.__on_graph_window_size_changed)
        self.graph_scroll_area.setWidget(self.__graph_layout)
        self.__plotable_items = None#self.__selected_item.get_plotable_items()
        self.__items_per_group = 1
        self.__expected_items_per_group = 1
        self.__number_of_groups = 1

        self.__update_graphs_lock = Lock()
        self.__first_update_pending = True

        self.__graph_dict = {}

        self.__plotted_curves = {}
        #self.create_graphs()

        self.__timer = Timer(Duration(secs=1.0), self.update_graphs)

    def __del__(self):
        self.__deleted = True

    def connect_slots(self):
        """
        Connects the slots.
        """
        # : tab_widget
        self.tab_widget.currentChanged.connect(self.__on_current_tab_changed)
        #: restart_push_button
        self.restart_push_button.clicked.connect(self.__on_restart_push_button_clicked)
        #: stop_push_button
        self.stop_push_button.clicked.connect(self.__on_stop_push_button_clicked)
        #: range_combo_box
        self.range_combo_box.currentIndexChanged.connect(self.__on_range_combo_box_index_changed)
        #pause button
        self.pause_button.clicked.connect(self.__on_pause_button_clicked)
        # selected combo box
        self.selected_combo_box.currentIndexChanged.connect(self.__on_selected_combo_box_index_changed)

    def create_graphs(self):
        """
        Creates the graphs for the plot.
        """
        self.__update_graphs_lock.acquire()
        if self.__selected_item is not None:
            first_iteration = True
            first_view = None
            i = 0
            self.__expected_items_per_group = 0
            self.__graph_layout.clear()

            if len(self.__plotable_items) is 0:
                raise UserWarning()
            for key in self.__plotable_items[min(self.__current_selected_combo_box_index *
                                                self.__items_per_group, len(self.__plotable_items)):
                                                min((self.__current_selected_combo_box_index + 1)
                                                * self.__items_per_group, len(self.__plotable_items))]:
                plot_widget = None
                if first_iteration:
                    first_iteration = False
                    date_axis = DateAxis(orientation="bottom")
                    first_view = pg.ViewBox()

                    plot_widget = self.__graph_layout.addPlot(title=self.tr(key), axisItems={'bottom': date_axis}, viewBox=first_view)
                else:

                    date_axis = DateAxis(orientation="bottom")
                    view_box = pg.ViewBox()
                    plot_widget = self.__graph_layout.addPlot(title=self.tr(key), viewBox=view_box, axisItems={'bottom': date_axis})
                    view_box.setXLink(first_view)

                #performance enhancements when only a short range of the plot is shown
                #plot_widget.setClipToView(clip=True)
                plot_widget.setYRange(-1, 1)
                self.__graph_dict[key] = plot_widget
                self.__graph_layout.nextRow()
                plot_widget = self.__graph_dict[key]
                plot_widget.showGrid(x=True, y=True)
                plot_widget.setMenuEnabled(enableMenu=True)
                plot_widget.enableAutoRange('xy', True)
                x = np.array([1])
                y = np.array([int(str(Time.now()))/1000000000])
                self.__plotted_curves[key] = plot_widget.plot(x=x, y=y, fillLevel=0, brush=(50, 50, 200, 100),
                                                              pen=(255, 0, 0))
                self.__expected_items_per_group += 1
            self.__first_update_pending = True
        self.__update_graphs_lock.release()


    def __on_graph_window_size_changed(self):
        # getting the size
        if self.__selected_item is not None:
            size = self.__graph_layout.size()
            items_per_group = max(int(math.ceil((size.height() - 100) / 200 + 1)), 1)
            if items_per_group is not self.__items_per_group or self.__selected_item_changed:
                self.__graph_layout.set_blocked(True)
                self.__items_per_group = items_per_group
                self.__number_of_groups = int(math.ceil(len(self.__plotable_items) / float(self.__items_per_group)))
                # change the groups in the widget
                self.selected_combo_box.clear()
                for group in range(0, self.__number_of_groups):
                    list = self.__plotable_items[min(group *
                                        self.__items_per_group, len(self.__plotable_items)):min((group + 1)
                                                                * self.__items_per_group, len(self.__plotable_items))]
                    content = ""
                    for i in range(0, len(list) - 1):
                        content += self.tr(list[i])
                        content += ", "
                    content += list[len(list) - 1]
                    self.selected_combo_box.addItem(content)
                # redraw
                self.create_graphs()
                self.update_graphs(None)
                self.__graph_layout.set_blocked(False)

    def __on_selected_combo_box_index_changed(self, index):
        """
        Updates what is shown in the graphs

        :param index: the index of the selected range
        :type index: int
        """
        if index is not -1:
            self.__current_selected_combo_box_index = index
            self.create_graphs()
            self.update_graphs(None)


    def __on_pause_button_clicked(self):
        """
        To be called whenever the pause button is clicked. Stops the graphs from updating until the pause button
        is clicked again and the other way.
        """
        if self.__draw_graphs:
            self.__draw_graphs = False
            self.pause_button.setText(self.tr("Continue"))
        else:
            self.__draw_graphs = True
            self.pause_button.setText(self.tr("Pause"))


    def set_selected_item(self, index):
        """
        Sets the selected item.

        :param index: the index of the selected item
        :type selected_item: QModelIndex
        """
        if index is not None:
            self.__update_graphs_lock.acquire()
            src_index = index.model().mapToSource(index)
            self.__selected_item = src_index.internalPointer()
            self.__log_filter_proxy.filter_by_item(self.__selected_item)
            if self.__selected_item is not None:
                self.__plotable_items = self.__selected_item.get_plotable_items()
                for key in self.__selected_item.get_list_items():
                    self.__plotable_items.remove(key)
                if self.__selected_item.can_execute_actions():
                    self.stop_push_button.setEnabled(True)
                    self.restart_push_button.setEnabled(True)
                else:
                    self.stop_push_button.setEnabled(False)
                    self.restart_push_button.setEnabled(False)
                self.__selected_item_changed = True
            self.__update_graphs_lock.release()
            self.update()
            self.__on_graph_window_size_changed()


    def __on_current_tab_changed(self, tab):
        """
        Will be called when switching between tabs.

        :param tab: index of the current tab
        :type tab: int
        """
        if tab is 1:
            self.__draw_graphs = True
        else:
            self.__draw_graphs = False


    def __on_restart_push_button_clicked(self):
        """
        Handels the restart button and restarts a host or node.
        """
        if self.__selected_item is not None:
            self.__selected_item.execute_action("restart")


    def __on_stop_push_button_clicked(self):
        """Handels the stop button and stops a host or node."""
        if self.__selected_item is not None:
            self.__selected_item.execute_action("stop")


    def __on_range_combo_box_index_changed(self, index):
        """
        Handels the change of the graph range.

        :param index: the index of the selected range
        :type index: int
        """
        self.__current_combo_box_index = index


    def update_graphs(self, event):
        """
        Updates and redraws the graphs.
        """
        self.__update_graphs_lock.acquire()
        if self.__selected_item is not None:
            if self.__draw_graphs or self.__first_update_pending:
                #print("items per group: " + str(self.__items_per_group))
                #print("combo index: " + str(self.__current_selected_combo_box_index))
                #print("len plot " + str(len(self.__plotable_items)))
                plotable_items = self.__plotable_items[min(self.__current_selected_combo_box_index *
                                    self.__items_per_group, len(self.__plotable_items)):min((self.__current_selected_combo_box_index + 1)
                                                            * self.__items_per_group, len(self.__plotable_items))]
                plotable_data = self.__selected_item.get_items_younger_than(
                    #Time.now() - Duration(secs=self.__combo_box_index_to_seconds(self.__current_range_combo_box_index)),
                    Time.now() - (Duration(secs=(self.__combo_box_index_to_seconds(self.__current_range_combo_box_index) + 10 )) if int(Duration(secs=self.__combo_box_index_to_seconds(self.__current_range_combo_box_index)).to_sec()) <= int(Time.now().to_sec()) else Time(0) ),
                    "window_stop", *plotable_items)
                if "window_stop" in plotable_data:
                    if plotable_data["window_stop"]:
                        temp_time = []
                        temp_content = []

                        length = len(plotable_data["window_stop"])
                        modulo = (length / 200) + 1

                        for i in range(0, length, modulo):
                            # now having maximally 100 items to plot :)
                            temp_time.append(plotable_data["window_stop"][i].to_sec())
                        x = np.array(temp_time)

                        list_entries = self.__selected_item.get_list_items()
                        time_entries = self.__selected_item.get_time_items()

                        for key in plotable_items:
                            if key in list_entries:
                                pass
                            else:
                                if key in time_entries:
                                    for i in range(0, length, modulo):
                                        temp_content.append(float(str(plotable_data[key][i]))/1000000000)
                                else:
                                    for i in range(0, length, modulo):
                                        temp_content.append(plotable_data[key][i])
                                y = np.array(temp_content)
                                del temp_content[:]
                                self.__plotted_curves[key].setData(x=x, y=y)
                    else:
                        pass

            self.__first_update_pending = False
        self.__update_graphs_lock.release()
      
    
    def update(self):
        """
        Updates the widget.
        """
        if not self.__deleted:
            if self.__selected_item is not None:
                data_dict = self.__selected_item.get_latest_data()
                self.__state = data_dict["state"]
                self.host_node_label.setText(self.tr(self.__selected_item.get_seuid()))

                if self.__previous_state is not self.__state:
                    self.__previous_state = self.__state
                    if self.__state == "ok":
                        self.current_status_label.setText(self.tr("ok"))
                        #self.host_node_label.setText(self.tr("Current Status: Ok"))
                        pixmap = QPixmap(os.path.join(self.rp.get_path('rqt_arni_gui_detail'), 'resources/graphics',
                                                      'block_green.png'))
                    elif self.__state == "warning":
                        self.current_status_label.setText(self.tr("warning"))
                        #self.host_node_label.setText(self.tr("Current Status: Warning"))
                        pixmap = QPixmap(os.path.join(self.rp.get_path('rqt_arni_gui_detail'), 'resources/graphics',
                                                      'block_orange.png'))
                    elif self.__state == "unknown":
                        self.current_status_label.setText(self.tr("unkown"))
                        #self.host_node_label.setText(self.tr("Current Status: Unkown"))
                        pixmap = QPixmap(os.path.join(self.rp.get_path('rqt_arni_gui_detail'), 'resources/graphics',
                                                      'block_grey.png'))
                    else: # error or offline
                        self.current_status_label.setText(self.tr(self.__state))
                        pixmap = QPixmap(os.path.join(self.rp.get_path('rqt_arni_gui_detail'), 'resources/graphics',
                                                      'block_red.png'))
                    self.status_light_label.setPixmap(pixmap)
                content = self.__selected_item.get_detailed_data()

                scroll_value = self.information_tab_text_browser.verticalScrollBar().value()
                self.information_tab_text_browser.setHtml(content)
                self.information_tab_text_browser.verticalScrollBar().setSliderPosition(scroll_value)
            else:
                self.host_node_label.setText(self.tr("No item selected"))
                self.current_status_label.setText(self.tr("Offline"))
                self.information_tab_text_browser.setText(self.tr("Please select an item in the TreeView to get more information"
                                                          " about it"))


    def __combo_box_index_to_seconds(self, index):
        """
        Calculates the range from the combo-box index.
        
        :param index: the index of teh combo-box
        :type index: int
        
        :returns: the seconds of the selected index 
        :rtype: int
        """
        if self.__current_combo_box_index == 0:
            return 10
        elif self.__current_combo_box_index == 1:
            return 30
        else:
            return 60


    def get_current_tab(self):
        """
        Returns the current tab.
        
        :returns: the current tab 
        :rtype: int
        """
        return self.tab_widget.currentIndex()


    def set_current_tab(self, index=0):
        """
        Sets the default tab.
        
        :param index: the index of the tab
        :type index: int
        """
        if index is None:
            index = 0
        self.tab_widget.setCurrentIndex(index)


    def get_range_combo_box_index(self):
        """
        Returns the index of the combo-box.
        
        :returns: the index
        :rtype: int
        """
        return self.range_combo_box.currentIndex()


    def set_range_combo_box_index(self, index=0):
        """
        Sets the default value of the combo-box.
        
        :param index: the index of the combo-box
        :type index: int
        """
        if index is None:
            index = 0
        self.range_combo_box.setCurrentIndex(index)
Example #7
0
    def __init__(self):
        """
        Initializes the widget.
        """
        super(OverviewWidget, self).__init__()

        # Get path to UI file which is a sibling of this file
        self.rp = rospkg.RosPack()
        ui_file = os.path.join(self.rp.get_path('rqt_arni_gui_overview'),
                               'resources', 'OverviewWidget.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self)

        self.__draw_graphs = False

        self.__log_delegate = LogDelegate()
        self.log_tab_tree_view.setItemDelegate(self.__log_delegate)

        self.__last_update = rospy.Time.now()

        self.__model = ROSModel()

        self.__log_filter_proxy = LogFilterProxy()

        self.__logger = self.__model.get_logger()
        self.__style_string = ".detailed_data_overview {\n" \
                               "    font-size: 13\n;" \
                               "}\n"

        self.information_tab_text_browser.setStyleSheet(self.__style_string)

        self.range_combo_box.clear()
        #todo: are these in the right order?
        self.range_combo_box.addItem("10 " + self.tr("Seconds"))
        self.range_combo_box.addItem("30 " + self.tr("Seconds"))
        #todo: adapt time!!!
        self.range_combo_box.addItem("60 " + self.tr("Seconds"))
        self.range_combo_box.setCurrentIndex(0)

        self.tab_widget.setTabText(0, self.tr("Information"))
        self.tab_widget.setTabText(1, self.tr("Graphs"))
        self.tab_widget.setTabText(2, self.tr("Log"))

        self.selected_label.setText(self.tr("Selected") + ":")
        self.range_label.setText(self.tr("Range") + ":")

        self.__log_filter_proxy.filter_by_item(None)
        self.__log_filter_proxy.setDynamicSortFilter(True)

        #set proxy model
        self.__log_filter_proxy.setSourceModel(
            self.__logger.get_representation())

        self.log_tab_tree_view.setModel(self.__log_filter_proxy)
        self.log_tab_tree_view.setRootIsDecorated(True)
        self.log_tab_tree_view.setAlternatingRowColors(True)
        self.log_tab_tree_view.setSortingEnabled(True)
        self.log_tab_tree_view.sortByColumn(1, Qt.AscendingOrder)

        self.__connect_slots()

        self.__state = "ok"
        self.__previous_state = "ok"

        self.__current_range_combo_box_index = 0
        self.__current_selected_combo_box_index = 0
        self.__last_update = rospy.Time.now()

        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.__graph_layout = ResizeableGraphicsLayoutWidget(
            self.__on_graph_window_size_changed)
        self.graph_scroll_area.setWidget(self.__graph_layout)
        self.__plotable_items = self.__model.get_root_item(
        ).get_plotable_items()
        self.__items_per_group = 1
        self.__expected_items_per_group = 1
        self.__number_of_groups = 1

        self.__update_graphs_lock = Lock()
        self.__first_update_pending = True

        self.__graph_dict = {}

        self.__first_resize = True

        self.__plotted_curves = {}
        self.create_graphs()

        self.__timer = Timer(Duration(secs=1.0), self.update_graphs)
Example #8
0
class OverviewWidget(QWidget):
    """
    The overviewWidget of the ArniGuiOverview-Plugin.
    """
    def __init__(self):
        """
        Initializes the widget.
        """
        super(OverviewWidget, self).__init__()

        # Get path to UI file which is a sibling of this file
        self.rp = rospkg.RosPack()
        ui_file = os.path.join(self.rp.get_path('rqt_arni_gui_overview'),
                               'resources', 'OverviewWidget.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self)

        self.__draw_graphs = False

        self.__log_delegate = LogDelegate()
        self.log_tab_tree_view.setItemDelegate(self.__log_delegate)

        self.__last_update = rospy.Time.now()

        self.__model = ROSModel()

        self.__log_filter_proxy = LogFilterProxy()

        self.__logger = self.__model.get_logger()
        self.__style_string = ".detailed_data_overview {\n" \
                               "    font-size: 13\n;" \
                               "}\n"

        self.information_tab_text_browser.setStyleSheet(self.__style_string)

        self.range_combo_box.clear()
        #todo: are these in the right order?
        self.range_combo_box.addItem("10 " + self.tr("Seconds"))
        self.range_combo_box.addItem("30 " + self.tr("Seconds"))
        #todo: adapt time!!!
        self.range_combo_box.addItem("60 " + self.tr("Seconds"))
        self.range_combo_box.setCurrentIndex(0)

        self.tab_widget.setTabText(0, self.tr("Information"))
        self.tab_widget.setTabText(1, self.tr("Graphs"))
        self.tab_widget.setTabText(2, self.tr("Log"))

        self.selected_label.setText(self.tr("Selected") + ":")
        self.range_label.setText(self.tr("Range") + ":")

        self.__log_filter_proxy.filter_by_item(None)
        self.__log_filter_proxy.setDynamicSortFilter(True)

        #set proxy model
        self.__log_filter_proxy.setSourceModel(
            self.__logger.get_representation())

        self.log_tab_tree_view.setModel(self.__log_filter_proxy)
        self.log_tab_tree_view.setRootIsDecorated(True)
        self.log_tab_tree_view.setAlternatingRowColors(True)
        self.log_tab_tree_view.setSortingEnabled(True)
        self.log_tab_tree_view.sortByColumn(1, Qt.AscendingOrder)

        self.__connect_slots()

        self.__state = "ok"
        self.__previous_state = "ok"

        self.__current_range_combo_box_index = 0
        self.__current_selected_combo_box_index = 0
        self.__last_update = rospy.Time.now()

        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.__graph_layout = ResizeableGraphicsLayoutWidget(
            self.__on_graph_window_size_changed)
        self.graph_scroll_area.setWidget(self.__graph_layout)
        self.__plotable_items = self.__model.get_root_item(
        ).get_plotable_items()
        self.__items_per_group = 1
        self.__expected_items_per_group = 1
        self.__number_of_groups = 1

        self.__update_graphs_lock = Lock()
        self.__first_update_pending = True

        self.__graph_dict = {}

        self.__first_resize = True

        self.__plotted_curves = {}
        self.create_graphs()

        self.__timer = Timer(Duration(secs=1.0), self.update_graphs)

    def __del__(self):
        """
        Destructor of the widget.
        """
        self.__draw_graphs = False
        self.__timer.stop()
        del self.__timer

    def create_graphs(self):
        """
        Creates the graphs for the plot.
        """
        self.__update_graphs_lock.acquire()
        first_iteration = True
        first_view = None
        i = 0
        self.__expected_items_per_group = 0
        self.__graph_layout.clear()

        for key in self.__plotable_items[min(
                self.__current_selected_combo_box_index *
                self.__items_per_group, len(self.__plotable_items)):min(
                    (self.__current_selected_combo_box_index + 1) *
                    self.__items_per_group, len(self.__plotable_items))]:
            plot_widget = None
            if first_iteration:
                first_iteration = False
                date_axis = DateAxis(orientation="bottom")
                first_view = pg.ViewBox()

                plot_widget = self.__graph_layout.addPlot(
                    title=self.tr(key),
                    axisItems={'bottom': date_axis},
                    viewBox=first_view)
            else:

                date_axis = DateAxis(orientation="bottom")
                view_box = pg.ViewBox()
                plot_widget = self.__graph_layout.addPlot(
                    title=self.tr(key),
                    viewBox=view_box,
                    axisItems={'bottom': date_axis})
                view_box.setXLink(first_view)

            #performance enhancements when only a short range of the plot is shown
            #plot_widget.setClipToView(clip=True)
            plot_widget.setYRange(-1, 1)
            self.__graph_dict[key] = plot_widget
            self.__graph_layout.nextRow()
            plot_widget = self.__graph_dict[key]
            plot_widget.showGrid(x=True, y=True)
            plot_widget.setMenuEnabled(enableMenu=True)
            plot_widget.enableAutoRange('xy', True)
            x = np.array([1])
            y = np.array([int(str(Time.now())) / 1000000000])
            self.__plotted_curves[key] = plot_widget.plot(x=x,
                                                          y=y,
                                                          fillLevel=0,
                                                          brush=(50, 50, 200,
                                                                 100),
                                                          pen=(255, 0, 0))
            self.__expected_items_per_group += 1
        self.__first_update_pending = True
        self.__update_graphs_lock.release()

    def __connect_slots(self):
        """
        Connects the slots.
        """
        self.tab_widget.currentChanged.connect(self.__on_current_tab_changed)
        self.range_combo_box.currentIndexChanged.connect(
            self.__on_range_combo_box_index_changed)
        self.__model.layoutChanged.connect(self.update)
        self.pause_button.clicked.connect(self.__on_pause_button_clicked)
        self.selected_combo_box.currentIndexChanged.connect(
            self.__on_selected_combo_box_index_changed)

    def __on_graph_window_size_changed(self):
        # getting the size
        size = self.__graph_layout.size()
        items_per_group = max(int(math.ceil((size.height() - 100) / 200 + 1)),
                              1)
        if items_per_group is not self.__items_per_group or self.__first_resize:
            self.__first_resize = False
            self.__graph_layout.set_blocked(True)
            self.__items_per_group = 1 if items_per_group < 1 else items_per_group
            self.__number_of_groups = int(
                math.ceil(
                    len(self.__plotable_items) /
                    float(self.__items_per_group)))
            # change the groups in the widget
            self.selected_combo_box.clear()
            for group in range(0, self.__number_of_groups):
                list = self.__plotable_items[min(
                    group *
                    self.__items_per_group, len(self.__plotable_items)):min(
                        (group + 1) *
                        self.__items_per_group, len(self.__plotable_items))]
                content = ""
                for i in range(0, len(list) - 1):
                    content += self.tr(list[i])
                    content += ", "
                content += list[len(list) - 1]
                self.selected_combo_box.addItem(content)
            # redraw
            self.create_graphs()
            self.update_graphs(None)
            self.__graph_layout.set_blocked(False)

    def __on_selected_combo_box_index_changed(self, index):
        """
        Updates what is shown in the graphs

        :param index: the index of the selected range
        :type index: int
        """
        if index is not -1:
            self.__current_selected_combo_box_index = index
            self.create_graphs()
            self.update_graphs(None)

    def __on_pause_button_clicked(self):
        """
        To be called whenever the pause button is clicked. Stops the graphs from updating until the pause button
        is clicked again and the other way.
        """
        if self.__draw_graphs:
            self.__draw_graphs = False
            self.pause_button.setText(self.tr("Continue"))
        else:
            self.__draw_graphs = True
            self.pause_button.setText(self.tr("Pause"))

    def __on_current_tab_changed(self, tab):
        """
        The Plugin wants to get notified when the tab changed so it can e.g. draw the graphs.

        :param tab: the index of the selected tab
        :type tab: int
        """
        if tab is 1:
            if self.pause_button.text() is not "Continue":
                self.__draw_graphs = True
            else:
                self.__draw_graphs = False
        else:
            self.__draw_graphs = False

    def __on_range_combo_box_index_changed(self, index):
        """
        Handels the change of the graph range.

        :param index: the index of the selected range
        :type index: int
        """
        self.__current_range_combo_box_index = index

    def update(self):
        """
        Updates the Plugin and draws the graphs if draw_graphs is true.
        """
        data_dict = self.__model.get_root_item().get_latest_data("state")

        self.__state = data_dict["state"]

        if self.__previous_state is not self.__state:
            self.__previous_state = self.__state
            if self.__state == "ok":
                self.status_text_line_edit.setText(
                    self.tr("Current status: Ok"))
                pixmap = QPixmap(
                    os.path.join(self.rp.get_path('rqt_arni_gui_overview'),
                                 'resources/graphics', 'light_green.png'))
            elif self.__state == "warning":
                self.status_text_line_edit.setText(
                    self.tr("Current status: Warning"))
                pixmap = QPixmap(
                    os.path.join(self.rp.get_path('rqt_arni_gui_overview'),
                                 'resources/graphics', 'light_orange.png'))
            else:
                self.status_text_line_edit.setText(
                    self.tr("Current status: Error"))
                pixmap = QPixmap(
                    os.path.join(self.rp.get_path('rqt_arni_gui_overview'),
                                 'resources/graphics', 'light_red.png'))
            self.status_light_label.setPixmap(pixmap)

        if self.information_tab_text_browser:
            scroll_value = self.information_tab_text_browser.verticalScrollBar(
            ).value()
            self.information_tab_text_browser.setHtml(
                self.__model.get_overview_text())
            self.information_tab_text_browser.verticalScrollBar(
            ).setSliderPosition(scroll_value)

    def update_graphs(self, event):
        """
        Updates and redraws the graphs.
        """
        self.__update_graphs_lock.acquire()
        if self.__draw_graphs or self.__first_update_pending:

            plotable_items = self.__plotable_items[min(
                self.__current_selected_combo_box_index *
                self.__items_per_group, len(self.__plotable_items)):min(
                    (self.__current_selected_combo_box_index + 1) *
                    self.__items_per_group, len(self.__plotable_items))]
            plotable_data = self.__model.get_root_item(
            ).get_items_younger_than(
                Time.now() - (Duration(secs=self.__combo_box_index_to_seconds(
                    self.__current_range_combo_box_index)) if int(
                        Duration(secs=self.__combo_box_index_to_seconds(
                            self.__current_range_combo_box_index)).to_sec()) <=
                              int(Time.now().to_sec()) else Time(0)),
                "window_stop", *plotable_items)
            temp_time = []
            temp_content = []

            if plotable_data["window_stop"]:
                modulo = (len(plotable_data["window_stop"]) / 200) + 1

                length = len(plotable_data["window_stop"])
            else:
                length = 0
                modulo = 1
            for i in range(0, length, modulo):
                # now having maximally 100 items to plot :)
                temp_time.append(
                    int(str(plotable_data["window_stop"][i])) / 1000000000)
            x = np.array(temp_time)

            for key in plotable_items:
                for i in range(0, length, modulo):
                    temp_content.append(plotable_data[key][i])
                y = np.array(temp_content)
                del temp_content[:]

                self.__plotted_curves[key].setData(x=x, y=y)

        self.__first_update_pending = False
        self.__update_graphs_lock.release()

    def __combo_box_index_to_seconds(self, index):
        """
        Calculates the range from the combo-box index.
        
        :param index: the index of teh combo-box
        :type index: int
        
        :returns: the seconds of the selected index 
        :rtype: int
        """
        if self.__current_range_combo_box_index == 0:
            return 10
        elif self.__current_range_combo_box_index == 1:
            return 30
        else:
            return 60

    def get_current_tab(self):
        """
        Returns the current tab.
        
        :returns: the current tab 
        :rtype: int
        """
        return self.tab_widget.currentIndex()

    def set_current_tab(self, index=0):
        """
        Sets the default tab.
        
        :param index: the index of the tab
        :type index: int
        """
        if index is None:
            index = 0
        self.tab_widget.setCurrentIndex(index)
        # WARNING: PROBABLY DOUBLE CALL OF __ON_CURRENT_TAB_CHANGED HERE BUT CANNOT BE FIXED SO EASILY
        self.__on_current_tab_changed(index)

    def get_range_combo_box_index(self):
        """
        Returns the index of the combo-box.
        
        :returns: the index 
        :rtype: int
        """
        return self.range_combo_box.currentIndex()

    def set_range_combo_box_index(self, index=0):
        """
        Sets the default value of the combo-box.
        
        :param index: the index of the combo-box
        :type index: int
        """
        if index is None:
            index = 0
        self.range_combo_box.setCurrentIndex(index)
Example #9
0
class SelectionWidget(QWidget):
    """
    The SelectionWidget of the ArniGuiDetail-Plugin.
    """
    def __init__(self, model):
        """
        Initializes the Widget.
        
        :param model: the model of the widget
        :type model: ROSModel
        """
        super(SelectionWidget, self).__init__()
        self.setObjectName('selection_widget')
        self.__model = model

        # Get path to UI file which is a sibling of this file
        self.rp = rospkg.RosPack()
        ui_file = os.path.join(self.rp.get_path('rqt_arni_gui_detail'),
                               'resources', 'SelectionWidget.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self)
        self.setObjectName('SelectionWidgetUi')

        self.__selected_item = None

        self.__draw_graphs = True
        self.__current_combo_box_index = 0

        self.__last_update = rospy.Time.now()

        try:
            if rospy.get_param("/enable_statistics") == False:
                raise KeyError('/enable_statistics')
        except KeyError:
            self.__overview_widget = None
            raise EnvironmentError(
                "/enable_statistics is either not set or set to false - arni gui would not work correctly. Please make sure to start "
                "roscore with the neccesary parameters or to load these while running (see init_params.launch)"
            )

        self.__values_dict = {
            "bandwidth_mean": 0,
            "bandwidth_stddev": 0,
            "bandwidth_max": 0,
        }

        self.__logger = self.__model.get_logger()
        self.__log_filter_proxy = LogFilterProxy()
        self.__log_filter_proxy.filter_by_item(self.__selected_item)
        self.__log_filter_proxy.setDynamicSortFilter(True)
        self.__log_filter_proxy.setSourceModel(
            self.__logger.get_representation())
        self.log_tab_tree_view.setModel(self.__log_filter_proxy)
        self.__log_delegate = LogDelegate()
        self.log_tab_tree_view.setItemDelegate(self.__log_delegate)

        self.__style_string = ".detailed_data {\n" \
                               "    font-size: 12\n;" \
                               "}\n"
        self.__style_string = ".erroneous_entry {\n" \
                               "    color: red\n;" \
                               "}\n"

        self.information_tab_text_browser.setStyleSheet(self.__style_string)

        self.range_combo_box.clear()
        self.range_combo_box.addItem("10 " + self.tr("Seconds"))
        self.range_combo_box.addItem("30 " + self.tr("Seconds"))
        self.range_combo_box.addItem("60 " + self.tr("Seconds"))
        self.range_combo_box.setCurrentIndex(0)

        #self.scrollAreaWidgetContents_2.setWidget(self.host_node_label)

        self.tab_widget.setTabText(0, self.tr("Information"))
        self.tab_widget.setTabText(1, self.tr("Graphs"))
        self.tab_widget.setTabText(2, self.tr("Log"))
        self.tab_widget.setTabText(3, self.tr("Actions"))

        self.stop_push_button.setText(self.tr("Stop Node"))
        self.restart_push_button.setText(self.tr("Restart Node"))
        self.stop_push_button.setEnabled(False)
        self.restart_push_button.setEnabled(False)

        self.selected_label.setText(self.tr("Selected") + ":")
        self.range_label.setText(self.tr("Range") + ":")

        self.log_tab_tree_view.setRootIsDecorated(False)
        self.log_tab_tree_view.setAlternatingRowColors(True)
        self.log_tab_tree_view.setSortingEnabled(True)
        self.log_tab_tree_view.sortByColumn(1, Qt.AscendingOrder)

        self.__current_range_combo_box_index = 0
        self.__current_selected_combo_box_index = 0

        self.set_selected_item(self.__selected_item)
        self.__model.layoutChanged.connect(self.update)

        self.__state = "ok"
        self.__previous_state = "ok"

        self.__selected_item_changed = True

        self.__deleted = False

        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.__graph_layout = ResizeableGraphicsLayoutWidget(
            self.__on_graph_window_size_changed)
        self.graph_scroll_area.setWidget(self.__graph_layout)
        self.__plotable_items = None  #self.__selected_item.get_plotable_items()
        self.__items_per_group = 1
        self.__expected_items_per_group = 1
        self.__number_of_groups = 1

        self.__update_graphs_lock = Lock()
        self.__first_update_pending = True

        self.__graph_dict = {}

        self.__plotted_curves = {}
        #self.create_graphs()

        self.__timer = Timer(Duration(secs=1.0), self.update_graphs)

    def __del__(self):
        self.__deleted = True

    def connect_slots(self):
        """
        Connects the slots.
        """
        # : tab_widget
        self.tab_widget.currentChanged.connect(self.__on_current_tab_changed)
        #: restart_push_button
        self.restart_push_button.clicked.connect(
            self.__on_restart_push_button_clicked)
        #: stop_push_button
        self.stop_push_button.clicked.connect(
            self.__on_stop_push_button_clicked)
        #: range_combo_box
        self.range_combo_box.currentIndexChanged.connect(
            self.__on_range_combo_box_index_changed)
        #pause button
        self.pause_button.clicked.connect(self.__on_pause_button_clicked)
        # selected combo box
        self.selected_combo_box.currentIndexChanged.connect(
            self.__on_selected_combo_box_index_changed)

    def create_graphs(self):
        """
        Creates the graphs for the plot.
        """
        self.__update_graphs_lock.acquire()
        if self.__selected_item is not None:
            first_iteration = True
            first_view = None
            i = 0
            self.__expected_items_per_group = 0
            self.__graph_layout.clear()

            if len(self.__plotable_items) is 0:
                raise UserWarning()
            for key in self.__plotable_items[min(
                    self.__current_selected_combo_box_index *
                    self.__items_per_group, len(self.__plotable_items)):min(
                        (self.__current_selected_combo_box_index + 1) *
                        self.__items_per_group, len(self.__plotable_items))]:
                plot_widget = None
                if first_iteration:
                    first_iteration = False
                    date_axis = DateAxis(orientation="bottom")
                    first_view = pg.ViewBox()

                    plot_widget = self.__graph_layout.addPlot(
                        title=self.tr(key),
                        axisItems={'bottom': date_axis},
                        viewBox=first_view)
                else:

                    date_axis = DateAxis(orientation="bottom")
                    view_box = pg.ViewBox()
                    plot_widget = self.__graph_layout.addPlot(
                        title=self.tr(key),
                        viewBox=view_box,
                        axisItems={'bottom': date_axis})
                    view_box.setXLink(first_view)

                #performance enhancements when only a short range of the plot is shown
                #plot_widget.setClipToView(clip=True)
                plot_widget.setYRange(-1, 1)
                self.__graph_dict[key] = plot_widget
                self.__graph_layout.nextRow()
                plot_widget = self.__graph_dict[key]
                plot_widget.showGrid(x=True, y=True)
                plot_widget.setMenuEnabled(enableMenu=True)
                plot_widget.enableAutoRange('xy', True)
                x = np.array([1])
                y = np.array([int(str(Time.now())) / 1000000000])
                self.__plotted_curves[key] = plot_widget.plot(x=x,
                                                              y=y,
                                                              fillLevel=0,
                                                              brush=(50, 50,
                                                                     200, 100),
                                                              pen=(255, 0, 0))
                self.__expected_items_per_group += 1
            self.__first_update_pending = True
        self.__update_graphs_lock.release()

    def __on_graph_window_size_changed(self):
        # getting the size
        if self.__selected_item is not None:
            size = self.__graph_layout.size()
            items_per_group = max(
                int(math.ceil((size.height() - 100) / 200 + 1)), 1)
            if items_per_group is not self.__items_per_group or self.__selected_item_changed:
                self.__graph_layout.set_blocked(True)
                self.__items_per_group = items_per_group
                self.__number_of_groups = int(
                    math.ceil(
                        len(self.__plotable_items) /
                        float(self.__items_per_group)))
                # change the groups in the widget
                self.selected_combo_box.clear()
                for group in range(0, self.__number_of_groups):
                    list = self.__plotable_items[min(
                        group *
                        self.__items_per_group, len(self.__plotable_items)
                    ):min((group + 1) *
                          self.__items_per_group, len(self.__plotable_items))]
                    content = ""
                    for i in range(0, len(list) - 1):
                        content += self.tr(list[i])
                        content += ", "
                    content += list[len(list) - 1]
                    self.selected_combo_box.addItem(content)
                # redraw
                self.create_graphs()
                self.update_graphs(None)
                self.__graph_layout.set_blocked(False)

    def __on_selected_combo_box_index_changed(self, index):
        """
        Updates what is shown in the graphs

        :param index: the index of the selected range
        :type index: int
        """
        if index is not -1:
            self.__current_selected_combo_box_index = index
            self.create_graphs()
            self.update_graphs(None)

    def __on_pause_button_clicked(self):
        """
        To be called whenever the pause button is clicked. Stops the graphs from updating until the pause button
        is clicked again and the other way.
        """
        if self.__draw_graphs:
            self.__draw_graphs = False
            self.pause_button.setText(self.tr("Continue"))
        else:
            self.__draw_graphs = True
            self.pause_button.setText(self.tr("Pause"))

    def set_selected_item(self, index):
        """
        Sets the selected item.

        :param index: the index of the selected item
        :type selected_item: QModelIndex
        """
        if index is not None:
            self.__update_graphs_lock.acquire()
            src_index = index.model().mapToSource(index)
            self.__selected_item = src_index.internalPointer()
            self.__log_filter_proxy.filter_by_item(self.__selected_item)
            if self.__selected_item is not None:
                self.__plotable_items = self.__selected_item.get_plotable_items(
                )
                for key in self.__selected_item.get_list_items():
                    self.__plotable_items.remove(key)
                if self.__selected_item.can_execute_actions():
                    self.stop_push_button.setEnabled(True)
                    self.restart_push_button.setEnabled(True)
                else:
                    self.stop_push_button.setEnabled(False)
                    self.restart_push_button.setEnabled(False)
                self.__selected_item_changed = True
            self.__update_graphs_lock.release()
            self.update()
            self.__on_graph_window_size_changed()

    def __on_current_tab_changed(self, tab):
        """
        Will be called when switching between tabs.

        :param tab: index of the current tab
        :type tab: int
        """
        if tab is 1:
            self.__draw_graphs = True
        else:
            self.__draw_graphs = False

    def __on_restart_push_button_clicked(self):
        """
        Handels the restart button and restarts a host or node.
        """
        if self.__selected_item is not None:
            self.__selected_item.execute_action("restart")

    def __on_stop_push_button_clicked(self):
        """Handels the stop button and stops a host or node."""
        if self.__selected_item is not None:
            self.__selected_item.execute_action("stop")

    def __on_range_combo_box_index_changed(self, index):
        """
        Handels the change of the graph range.

        :param index: the index of the selected range
        :type index: int
        """
        self.__current_combo_box_index = index

    def update_graphs(self, event):
        """
        Updates and redraws the graphs.
        """
        self.__update_graphs_lock.acquire()
        if self.__selected_item is not None:
            if self.__draw_graphs or self.__first_update_pending:
                #print("items per group: " + str(self.__items_per_group))
                #print("combo index: " + str(self.__current_selected_combo_box_index))
                #print("len plot " + str(len(self.__plotable_items)))
                plotable_items = self.__plotable_items[min(
                    self.__current_selected_combo_box_index *
                    self.__items_per_group, len(self.__plotable_items)):min(
                        (self.__current_selected_combo_box_index + 1) *
                        self.__items_per_group, len(self.__plotable_items))]
                plotable_data = self.__selected_item.get_items_younger_than(
                    #Time.now() - Duration(secs=self.__combo_box_index_to_seconds(self.__current_range_combo_box_index)),
                    Time.now() -
                    (Duration(secs=(self.__combo_box_index_to_seconds(
                        self.__current_range_combo_box_index) + 10)) if int(
                            Duration(secs=self.__combo_box_index_to_seconds(
                                self.__current_range_combo_box_index)).to_sec(
                                )) <= int(Time.now().to_sec()) else Time(0)),
                    "window_stop",
                    *plotable_items)
                if "window_stop" in plotable_data:
                    if plotable_data["window_stop"]:
                        temp_time = []
                        temp_content = []

                        length = len(plotable_data["window_stop"])
                        modulo = (length / 200) + 1

                        for i in range(0, length, modulo):
                            # now having maximally 100 items to plot :)
                            temp_time.append(
                                plotable_data["window_stop"][i].to_sec())
                        x = np.array(temp_time)

                        list_entries = self.__selected_item.get_list_items()
                        time_entries = self.__selected_item.get_time_items()

                        for key in plotable_items:
                            if key in list_entries:
                                pass
                            else:
                                if key in time_entries:
                                    for i in range(0, length, modulo):
                                        temp_content.append(
                                            float(str(plotable_data[key][i])) /
                                            1000000000)
                                else:
                                    for i in range(0, length, modulo):
                                        temp_content.append(
                                            plotable_data[key][i])
                                y = np.array(temp_content)
                                del temp_content[:]
                                self.__plotted_curves[key].setData(x=x, y=y)
                    else:
                        pass

            self.__first_update_pending = False
        self.__update_graphs_lock.release()

    def update(self):
        """
        Updates the widget.
        """
        if not self.__deleted:
            if self.__selected_item is not None:
                data_dict = self.__selected_item.get_latest_data()
                self.__state = data_dict["state"]
                self.host_node_label.setText(
                    self.tr(self.__selected_item.get_seuid()))

                if self.__previous_state is not self.__state:
                    self.__previous_state = self.__state
                    if self.__state == "ok":
                        self.current_status_label.setText(self.tr("ok"))
                        #self.host_node_label.setText(self.tr("Current Status: Ok"))
                        pixmap = QPixmap(
                            os.path.join(
                                self.rp.get_path('rqt_arni_gui_detail'),
                                'resources/graphics', 'block_green.png'))
                    elif self.__state == "warning":
                        self.current_status_label.setText(self.tr("warning"))
                        #self.host_node_label.setText(self.tr("Current Status: Warning"))
                        pixmap = QPixmap(
                            os.path.join(
                                self.rp.get_path('rqt_arni_gui_detail'),
                                'resources/graphics', 'block_orange.png'))
                    elif self.__state == "unknown":
                        self.current_status_label.setText(self.tr("unkown"))
                        #self.host_node_label.setText(self.tr("Current Status: Unkown"))
                        pixmap = QPixmap(
                            os.path.join(
                                self.rp.get_path('rqt_arni_gui_detail'),
                                'resources/graphics', 'block_grey.png'))
                    else:  # error or offline
                        self.current_status_label.setText(self.tr(
                            self.__state))
                        pixmap = QPixmap(
                            os.path.join(
                                self.rp.get_path('rqt_arni_gui_detail'),
                                'resources/graphics', 'block_red.png'))
                    self.status_light_label.setPixmap(pixmap)
                content = self.__selected_item.get_detailed_data()

                scroll_value = self.information_tab_text_browser.verticalScrollBar(
                ).value()
                self.information_tab_text_browser.setHtml(content)
                self.information_tab_text_browser.verticalScrollBar(
                ).setSliderPosition(scroll_value)
            else:
                self.host_node_label.setText(self.tr("No item selected"))
                self.current_status_label.setText(self.tr("Offline"))
                self.information_tab_text_browser.setText(
                    self.
                    tr("Please select an item in the TreeView to get more information"
                       " about it"))

    def __combo_box_index_to_seconds(self, index):
        """
        Calculates the range from the combo-box index.
        
        :param index: the index of teh combo-box
        :type index: int
        
        :returns: the seconds of the selected index 
        :rtype: int
        """
        if self.__current_combo_box_index == 0:
            return 10
        elif self.__current_combo_box_index == 1:
            return 30
        else:
            return 60

    def get_current_tab(self):
        """
        Returns the current tab.
        
        :returns: the current tab 
        :rtype: int
        """
        return self.tab_widget.currentIndex()

    def set_current_tab(self, index=0):
        """
        Sets the default tab.
        
        :param index: the index of the tab
        :type index: int
        """
        if index is None:
            index = 0
        self.tab_widget.setCurrentIndex(index)

    def get_range_combo_box_index(self):
        """
        Returns the index of the combo-box.
        
        :returns: the index
        :rtype: int
        """
        return self.range_combo_box.currentIndex()

    def set_range_combo_box_index(self, index=0):
        """
        Sets the default value of the combo-box.
        
        :param index: the index of the combo-box
        :type index: int
        """
        if index is None:
            index = 0
        self.range_combo_box.setCurrentIndex(index)