raw_view.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2012, Willow Garage, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Willow Garage, Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 """
33 Defines a raw view: a TopicMessageView that displays the message contents in a tree.
34 """
35 import rospy
36 import codecs
37 import math
38 
39 from python_qt_binding.QtCore import Qt
40 try: # indigo
41  from python_qt_binding.QtGui import QApplication, QAbstractItemView, QSizePolicy, QTreeWidget, QTreeWidgetItem
42 except ImportError: # kinetic+ (pyqt5)
43  from python_qt_binding.QtWidgets import QApplication, QAbstractItemView, QSizePolicy, QTreeWidget, QTreeWidgetItem
44 from .topic_message_view import TopicMessageView
45 
46 
47 class RawView(TopicMessageView):
48  name = 'Raw'
49  """
50  Plugin to view a message in a treeview window
51  The message is loaded into a custum treewidget
52  """
53  def __init__(self, timeline, parent, topic):
54  """
55  :param timeline: timeline data object, ''BagTimeline''
56  :param parent: widget that will be added to the ros_gui context, ''QWidget''
57  """
58  super(RawView, self).__init__(timeline, parent, topic)
59  self.message_tree = MessageTree(parent)
60  parent.layout().addWidget(self.message_tree) # This will automatically resize the message_tree to the windowsize
61 
62  def message_viewed(self, bag, msg_details):
63  super(RawView, self).message_viewed(bag, msg_details)
64  _, msg, t = msg_details # topic, msg, t = msg_details
65  if t is None:
66  self.message_cleared()
67  else:
68  self.message_tree.set_message(msg)
69 
70  def message_cleared(self):
71  TopicMessageView.message_cleared(self)
72  self.message_tree.set_message(None)
73 
74 
75 class MessageTree(QTreeWidget):
76  def __init__(self, parent):
77  super(MessageTree, self).__init__(parent)
78  self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
79  self.setHeaderHidden(True)
80  self.setSelectionMode(QAbstractItemView.ExtendedSelection)
81  self._msg = None
82 
83  self._expanded_paths = None
85 
86  @property
87  def msg(self):
88  return self._msg
89 
90  def set_message(self, msg):
91  """
92  Clears the tree view and displays the new message
93  :param msg: message object to display in the treeview, ''msg''
94  """
95  # Remember whether items were expanded or not before deleting
96  if self._msg:
97  for item in self.get_all_items():
98  path = self.get_item_path(item)
99  if item.isExpanded():
100  self._expanded_paths.add(path)
101  elif path in self._expanded_paths:
102  self._expanded_paths.remove(path)
103  self.clear()
104  if msg:
105  # Populate the tree
106  self._add_msg_object(None, '', '', msg, msg._type)
107 
108  if self._expanded_paths is None:
109  self._expanded_paths = set()
110  else:
111  # Expand those that were previously expanded, and collapse any paths that we've seen for the first time
112  for item in self.get_all_items():
113  path = self.get_item_path(item)
114  if path in self._expanded_paths:
115  item.setExpanded(True)
116  else:
117  item.setExpanded(False)
118  self._msg = msg
119  self.update()
120 
121  # Keyboard handler
122  def on_key_press(self, event):
123  key, ctrl = event.key(), event.modifiers() & Qt.ControlModifier
124  if ctrl:
125  if key == ord('C') or key == ord('c'):
126  # Ctrl-C: copy text from selected items to clipboard
128  event.accept()
129  elif key == ord('A') or key == ord('a'):
130  # Ctrl-A: select all
131  self._select_all()
132 
133  def _select_all(self):
134  for i in self.get_all_items():
135  if not i.isSelected():
136  i.setSelected(True)
137  i.setExpanded(True)
138 
140  # Get tab indented text for all selected items
141  def get_distance(item, ancestor, distance=0):
142  parent = item.parent()
143  if parent == None:
144  return distance
145  else:
146  return get_distance(parent, ancestor, distance + 1)
147  text = ''
148  for i in self.get_all_items():
149  if i in self.selectedItems():
150  text += ('\t' * (get_distance(i, None))) + i.text(0) + '\n'
151  # Copy the text to the clipboard
152  clipboard = QApplication.clipboard()
153  clipboard.setText(text)
154 
155  def get_item_path(self, item):
156  return item.data(0, Qt.UserRole)[0].replace(' ', '') # remove spaces that may get introduced in indexing, e.g. [ 3] is [3]
157 
158  def get_all_items(self):
159  items = []
160  try:
161  root = self.invisibleRootItem()
162  self.traverse(root, items.append)
163  except Exception:
164  # TODO: very large messages can cause a stack overflow due to recursion
165  pass
166  return items
167 
168  def traverse(self, root, function):
169  for i in range(root.childCount()):
170  child = root.child(i)
171  function(child)
172  self.traverse(child, function)
173 
174  def _add_msg_object(self, parent, path, name, obj, obj_type):
175  label = name
176 
177  if hasattr(obj, '__slots__'):
178  subobjs = [(slot, getattr(obj, slot)) for slot in obj.__slots__]
179  elif type(obj) in [list, tuple]:
180  len_obj = len(obj)
181  if len_obj == 0:
182  subobjs = []
183  else:
184  w = int(math.ceil(math.log10(len_obj)))
185  subobjs = [('[%*d]' % (w, i), subobj) for (i, subobj) in enumerate(obj)]
186  else:
187  subobjs = []
188 
189  if type(obj) in [int, long, float]:
190  if type(obj) == float:
191  obj_repr = '%.6f' % obj
192  else:
193  obj_repr = str(obj)
194 
195  if obj_repr[0] == '-':
196  label += ': %s' % obj_repr
197  else:
198  label += ': %s' % obj_repr
199 
200  elif type(obj) in [str, bool, int, long, float, complex, rospy.Time]:
201  # Ignore any binary data
202  obj_repr = codecs.utf_8_decode(str(obj), 'ignore')[0]
203 
204  # Truncate long representations
205  if len(obj_repr) >= 50:
206  obj_repr = obj_repr[:50] + '...'
207 
208  label += ': ' + obj_repr
209  item = QTreeWidgetItem([label])
210  if name == '':
211  pass
212  elif path.find('.') == -1 and path.find('[') == -1:
213  self.addTopLevelItem(item)
214  else:
215  parent.addChild(item)
216  item.setData(0, Qt.UserRole, (path, obj_type))
217 
218  for subobj_name, subobj in subobjs:
219  if subobj is None:
220  continue
221 
222  if path == '':
223  subpath = subobj_name # root field
224  elif subobj_name.startswith('['):
225  subpath = '%s%s' % (path, subobj_name) # list, dict, or tuple
226  else:
227  subpath = '%s.%s' % (path, subobj_name) # attribute (prefix with '.')
228 
229  if hasattr(subobj, '_type'):
230  subobj_type = subobj._type
231  else:
232  subobj_type = type(subobj).__name__
233 
234  self._add_msg_object(item, subpath, subobj_name, subobj, subobj_type)
def message_viewed(self, bag, msg_details)
Definition: raw_view.py:62
def _add_msg_object(self, parent, path, name, obj, obj_type)
Definition: raw_view.py:174
def traverse(self, root, function)
Definition: raw_view.py:168
def __init__(self, timeline, parent, topic)
Definition: raw_view.py:53


rqt_py_trees
Author(s): Thibault Kruse, Michal Staniaszek, Daniel Stonier, Naveed Usmani
autogenerated on Mon Jun 10 2019 14:55:56