messages_widget.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 import os
00034 
00035 from python_qt_binding import loadUi
00036 from python_qt_binding.QtCore import Qt
00037 from python_qt_binding.QtGui import QIcon
00038 from python_qt_binding.QtWidgets import (QAction, QMenu, QMessageBox,
00039                                          QTreeView, QWidget)
00040 import roslib
00041 import rosmsg
00042 import rospkg
00043 import rospy
00044 
00045 
00046 from .messages_tree_view import MessagesTreeView
00047 from rqt_py_common import rosaction
00048 from rqt_console.text_browse_dialog import TextBrowseDialog
00049 
00050 
00051 class MessagesWidget(QWidget):
00052 
00053     """
00054     This class is intended to be able to handle msg, srv & action (actionlib).
00055     The name of the class is kept to use message, by following the habit of
00056     rosmsg (a script that can handle both msg & srv).
00057     """
00058 
00059     def __init__(self, mode=rosmsg.MODE_MSG,
00060                  pkg_name='rqt_msg',
00061                  ui_filename='messages.ui'):
00062         """
00063         :param ui_filename: This Qt-based .ui file must have elements that are
00064                             referred from this class. Otherwise unexpected
00065                             errors are likely to happen. Best way to avoid that
00066                             situation when you want to give your own .ui file
00067                             is to implement all Qt components in
00068                             rqt_msg/resource/message.ui file.
00069         """
00070 
00071         super(MessagesWidget, self).__init__()
00072         self._rospack = rospkg.RosPack()
00073         ui_file = os.path.join(self._rospack.get_path(pkg_name), 'resource', ui_filename)
00074         loadUi(ui_file, self, {'MessagesTreeView': MessagesTreeView})
00075         self.setObjectName(ui_filename)
00076         self._mode = mode
00077 
00078         self._add_button.setIcon(QIcon.fromTheme('list-add'))
00079         self._add_button.clicked.connect(self._add_message)
00080         self._refresh_packages(mode)
00081         self._refresh_msgs(self._package_combo.itemText(0))
00082         self._package_combo.currentIndexChanged[str].connect(self._refresh_msgs)
00083         self._messages_tree.mousePressEvent = self._handle_mouse_press
00084 
00085         self._browsers = []
00086 
00087     def _refresh_packages(self, mode=rosmsg.MODE_MSG):
00088         if (self._mode == rosmsg.MODE_MSG) or self._mode == rosmsg.MODE_SRV:
00089             packages = sorted([pkg_tuple[0] for pkg_tuple in
00090                                rosmsg.iterate_packages(self._rospack, self._mode)])
00091         elif self._mode == rosaction.MODE_ACTION:
00092             packages = sorted([pkg_tuple[0]
00093                                for pkg_tuple in rosaction.iterate_packages(
00094                 self._rospack, self._mode)])
00095         self._package_list = packages
00096         rospy.logdebug('pkgs={}'.format(self._package_list))
00097         self._package_combo.clear()
00098         self._package_combo.addItems(self._package_list)
00099         self._package_combo.setCurrentIndex(0)
00100 
00101     def _refresh_msgs(self, package=None):
00102         if package is None or len(package) == 0:
00103             return
00104         self._msgs = []
00105         if (self._mode == rosmsg.MODE_MSG or
00106                 self._mode == rosaction.MODE_ACTION):
00107             msg_list = rosmsg.list_msgs(package)
00108         elif self._mode == rosmsg.MODE_SRV:
00109             msg_list = rosmsg.list_srvs(package)
00110 
00111         rospy.logdebug(
00112             '_refresh_msgs package={} msg_list={}'.format(package, msg_list))
00113         for msg in msg_list:
00114             if (self._mode == rosmsg.MODE_MSG or
00115                     self._mode == rosaction.MODE_ACTION):
00116                 msg_class = roslib.message.get_message_class(msg)
00117             elif self._mode == rosmsg.MODE_SRV:
00118                 msg_class = roslib.message.get_service_class(msg)
00119 
00120             rospy.logdebug('_refresh_msgs msg_class={}'.format(msg_class))
00121 
00122             if msg_class is not None:
00123                 self._msgs.append(msg)
00124 
00125         self._msgs = [x.split('/')[1] for x in self._msgs]
00126 
00127         self._msgs_combo.clear()
00128         self._msgs_combo.addItems(self._msgs)
00129 
00130     def _add_message(self):
00131         if self._msgs_combo.count() == 0:
00132             return
00133         msg = (self._package_combo.currentText() +
00134                '/' + self._msgs_combo.currentText())
00135 
00136         rospy.logdebug('_add_message msg={}'.format(msg))
00137 
00138         if (self._mode == rosmsg.MODE_MSG or
00139                 self._mode == rosaction.MODE_ACTION):
00140             msg_class = roslib.message.get_message_class(msg)()
00141             if self._mode == rosmsg.MODE_MSG:
00142                 text_tree_root = 'Msg Root'
00143             elif self._mode == rosaction.MODE_ACTION:
00144                 text_tree_root = 'Action Root'
00145             self._messages_tree.model().add_message(msg_class,
00146                                                     self.tr(text_tree_root), msg, msg)
00147 
00148         elif self._mode == rosmsg.MODE_SRV:
00149             msg_class = roslib.message.get_service_class(msg)()
00150             self._messages_tree.model().add_message(msg_class._request_class,
00151                                                     self.tr('Service Request'),
00152                                                     msg, msg)
00153             self._messages_tree.model().add_message(msg_class._response_class,
00154                                                     self.tr('Service Response'),
00155                                                     msg, msg)
00156         self._messages_tree._recursive_set_editable(
00157             self._messages_tree.model().invisibleRootItem(), False)
00158 
00159     def _handle_mouse_press(self, event,
00160                             old_pressEvent=QTreeView.mousePressEvent):
00161         if (event.buttons() & Qt.RightButton and
00162                 event.modifiers() == Qt.NoModifier):
00163             self._rightclick_menu(event)
00164             event.accept()
00165         return old_pressEvent(self._messages_tree, event)
00166 
00167     def _rightclick_menu(self, event):
00168         """
00169         :type event: QEvent
00170         """
00171 
00172         # QTreeview.selectedIndexes() returns 0 when no node is selected.
00173         # This can happen when after booting no left-click has been made yet
00174         # (ie. looks like right-click doesn't count). These lines are the
00175         # workaround for that problem.
00176         selected = self._messages_tree.selectedIndexes()
00177         if len(selected) == 0:
00178             return
00179 
00180         menu = QMenu()
00181         text_action = QAction(self.tr('View Text'), menu)
00182         menu.addAction(text_action)
00183         raw_action = QAction(self.tr('View Raw'), menu)
00184         menu.addAction(raw_action)
00185         remove_action = QAction(self.tr('Remove message'), menu)
00186         menu.addAction(remove_action)
00187 
00188         action = menu.exec_(event.globalPos())
00189 
00190         if action == raw_action or action == text_action:
00191             rospy.logdebug('_rightclick_menu selected={}'.format(selected))
00192             selected_type = selected[1].data()
00193 
00194             if selected_type[-2:] == '[]':
00195                 selected_type = selected_type[:-2]
00196             browsetext = None
00197             try:
00198                 if (self._mode == rosmsg.MODE_MSG or
00199                         self._mode == rosaction.MODE_ACTION):
00200                     browsetext = rosmsg.get_msg_text(selected_type,
00201                                                      action == raw_action)
00202                 elif self._mode == rosmsg.MODE_SRV:
00203                     browsetext = rosmsg.get_srv_text(selected_type,
00204                                                      action == raw_action)
00205 
00206                 else:
00207                     raise
00208             except rosmsg.ROSMsgException as e:
00209                 QMessageBox.warning(self, self.tr('Warning'),
00210                                     self.tr('The selected item component ' +
00211                                             'does not have text to view.'))
00212             if browsetext is not None:
00213                 self._browsers.append(TextBrowseDialog(browsetext,
00214                                                        self._rospack))
00215                 self._browsers[-1].show()
00216 
00217         if action == remove_action:
00218             self._messages_tree.model().removeRow(selected[0].row())
00219 
00220     def cleanup_browsers_on_close(self):
00221         for browser in self._browsers:
00222             browser.close()


rqt_msg
Author(s): Aaron Blasdel
autogenerated on Thu Jun 6 2019 21:23:16