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


rqt_msg
Author(s): Aaron Blasdel
autogenerated on Mon Oct 6 2014 07:15:17