inspector_window.py
Go to the documentation of this file.
00001 # Software License Agreement (BSD License)
00002 #
00003 # Copyright (c) 2012, Willow Garage, Inc.
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #  * Redistributions of source code must retain the above copyright
00011 #    notice, this list of conditions and the following disclaimer.
00012 #  * Redistributions in binary form must reproduce the above
00013 #    copyright notice, this list of conditions and the following
00014 #    disclaimer in the documentation and/or other materials provided
00015 #    with the distribution.
00016 #  * Neither the name of Willow Garage, Inc. nor the names of its
00017 #    contributors may be used to endorse or promote products derived
00018 #    from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
00032 #
00033 # Author: Isaac Saito, Ze'ev Klapow
00034 
00035 from python_qt_binding.QtCore import Signal
00036 from python_qt_binding.QtGui import QPushButton, QTextEdit, QVBoxLayout
00037 import rospy
00038 
00039 from rqt_robot_monitor.abst_status_widget import AbstractStatusWidget
00040 from rqt_robot_monitor.status_snapshot import StatusSnapshot
00041 from rqt_robot_monitor.time_pane import TimelinePane
00042 from rqt_robot_monitor.util_robot_monitor import Util
00043 
00044 
00045 class InspectorWindow(AbstractStatusWidget):
00046     _sig_write = Signal(str, str)
00047     _sig_newline = Signal()
00048     _sig_close_window = Signal()
00049     _sig_clear = Signal()
00050 
00051     def __init__(self, status, close_callback):
00052         """
00053         :type status: DiagnosticStatus
00054         :param close_callback: When the instance of this class
00055                                (InspectorWindow) terminates, this callback gets
00056                                called.
00057         """
00058         #TODO(Isaac) UI construction that currently is done in this method,
00059         #            needs to be done in .ui file.
00060 
00061         super(InspectorWindow, self).__init__()
00062         self.status = status
00063         self._close_callback = close_callback
00064         self.setWindowTitle(status.name)
00065         self.paused = False
00066 
00067         self.layout_vertical = QVBoxLayout(self)
00068 
00069         self.disp = QTextEdit(self)
00070         self.snapshot = QPushButton("StatusSnapshot")
00071 
00072         self.timeline_pane = TimelinePane(self)
00073         self.timeline_pane.set_timeline_data(Util.SECONDS_TIMELINE,
00074                                              self.get_color_for_value,
00075                                              self.on_pause)
00076 
00077         self.layout_vertical.addWidget(self.disp, 1)
00078         self.layout_vertical.addWidget(self.timeline_pane, 0)
00079         self.layout_vertical.addWidget(self.snapshot)
00080 
00081         self.snaps = []
00082         self.snapshot.clicked.connect(self._take_snapshot)
00083 
00084         self._sig_write.connect(self._write_key_val)
00085         self._sig_newline.connect(lambda: self.disp.insertPlainText('\n'))
00086         self._sig_clear.connect(lambda: self.disp.clear())
00087         self._sig_close_window.connect(self._close_callback)
00088 
00089         self.setLayout(self.layout_vertical)
00090         # TODO better to be configurable where to appear.
00091         self.setGeometry(0, 0, 400, 600)
00092         self.show()
00093         self.update_status_display(status)
00094 
00095     def closeEvent(self, event):
00096         # emit signal that should be slotted by StatusItem
00097         self._sig_close_window.emit()
00098         self.close()
00099 
00100     def _write_key_val(self, k, v):
00101         self.disp.setFontWeight(75)
00102         self.disp.insertPlainText(k)
00103         self.disp.insertPlainText(': ')
00104 
00105         self.disp.setFontWeight(50)
00106         self.disp.insertPlainText(v)
00107         self.disp.insertPlainText('\n')
00108 
00109     def pause(self, msg):
00110         rospy.logdebug('InspectorWin pause PAUSED')
00111         self.paused = True
00112         self.update_status_display(msg)
00113 
00114     def unpause(self, msg):
00115         rospy.logdebug('InspectorWin pause UN-PAUSED')
00116         self.paused = False
00117 
00118     def new_diagnostic(self, msg, is_forced=False):
00119         """
00120         Overridden from AbstractStatusWidget
00121 
00122         :type status: DiagnosticsStatus
00123         """
00124 
00125         if not self.paused:
00126             self.update_status_display(msg)
00127             rospy.logdebug('InspectorWin _cb len of queue=%d self.paused=%s',
00128                           len(self.timeline_pane._queue_diagnostic),
00129                           self.paused)
00130         else:
00131             if is_forced:
00132                 self.update_status_display(msg, True)
00133                 rospy.logdebug('@@@InspectorWin _cb PAUSED window updated')
00134             else:
00135                 rospy.logdebug('@@@InspectorWin _cb PAUSED not updated')
00136 
00137     def update_status_display(self, status, is_forced=False):
00138         """
00139         :type status: DiagnosticsStatus
00140         """
00141 
00142         if not self.paused or (self.paused and is_forced):
00143             scroll_value = self.disp.verticalScrollBar().value()
00144             self.timeline_pane.new_diagnostic(status)
00145 
00146             rospy.logdebug('InspectorWin update_status_display 1')
00147 
00148             self.status = status
00149             self._sig_clear.emit()
00150             self._sig_write.emit("Full Name", status.name)
00151             self._sig_write.emit("Component", status.name.split('/')[-1])
00152             self._sig_write.emit("Hardware ID", status.hardware_id)
00153             self._sig_write.emit("Level", str(status.level))
00154             self._sig_write.emit("Message", status.message)
00155             self._sig_newline.emit()
00156 
00157             for v in status.values:
00158                 self._sig_write.emit(v.key, v.value)
00159             if self.disp.verticalScrollBar().maximum() < scroll_value:
00160                 scroll_value = self.disp.verticalScrollBar().maximum()
00161             self.disp.verticalScrollBar().setValue(scroll_value)
00162 
00163     def _take_snapshot(self):
00164         snap = StatusSnapshot(self.status)
00165         self.snaps.append(snap)
00166 
00167     def get_color_for_value(self, queue_diagnostic, color_index):
00168         """
00169         Overridden from AbstractStatusWidget.
00170 
00171         :type color_index: int
00172         """
00173 
00174         rospy.logdebug('InspectorWindow get_color_for_value ' +
00175                        'queue_diagnostic=%d, color_index=%d',
00176                        len(queue_diagnostic), color_index)
00177         lv_index = queue_diagnostic[color_index - 1].level
00178         return Util.COLOR_DICT[lv_index]


rqt_robot_monitor
Author(s): Isaac Saito, Ze'ev Klapow, Kevin Watts, Josh Faust
autogenerated on Mon Oct 6 2014 07:16:09