timeline_menu.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2009, 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 from python_qt_binding.QtWidgets import QVBoxLayout, QMenu, QWidget, QDockWidget
34 
35 
36 class TopicPopupWidget(QWidget):
37 
38  def __init__(self, popup_name, timeline, viewer_type, topic):
39  super(TopicPopupWidget, self).__init__()
40  self.setObjectName(popup_name)
41  self.setWindowTitle(popup_name)
42 
43  layout = QVBoxLayout()
44  self.setLayout(layout)
45 
46  self._timeline = timeline
47  self._viewer_type = viewer_type
48  self._topic = topic
49  self._viewer = None
50  self._is_listening = False
51 
52  def hideEvent(self, event):
53  if self._is_listening:
54  self._timeline.remove_listener(self._topic, self._viewer)
55  self._is_listening = False
56  super(TopicPopupWidget, self).hideEvent(event)
57 
58  def showEvent(self, event):
59  if not self._is_listening:
60  self._timeline.add_listener(self._topic, self._viewer)
61  self._is_listening = True
62  super(TopicPopupWidget, self).showEvent(event)
63 
64  def show(self, context):
65  """
66  Make this topic popup visible, if necessary. This includes setting up
67  the proper close button hacks
68  """
69  if not self.parent():
70  context.add_widget(self)
71  # make the dock widget closable, even if it normally isn't
72  dock_features = self.parent().features()
73  dock_features |= QDockWidget.DockWidgetClosable
74  self.parent().setFeatures(dock_features)
75 
76  # remove old listener
77  if self._viewer:
78  self._timeline.remove_listener(self._topic, self._viewer)
79  self._viewer = None
80 
81  # Clean out the layout. Loop backwards since removing
82  # from the beginning shifts items and changes the order
83  for i in reversed(range(self.layout().count())):
84  self.layout().itemAt(i).widget().setParent(None)
85 
86  # create a new viewer
87  self._viewer = self._viewer_type(self._timeline, self, self._topic)
88  if not self._is_listening:
89  self._timeline.add_listener(self._topic, self._viewer)
90  self._is_listening = True
91 
92  super(TopicPopupWidget, self).show()
93 
94 
95 class TimelinePopupMenu(QMenu):
96 
97  """
98  Custom popup menu displayed on rightclick from timeline
99  """
100 
101  def __init__(self, timeline, event, menu_topic):
102  super(TimelinePopupMenu, self).__init__()
103 
104  self.parent = timeline
105  self.timeline = timeline
106 
107  if menu_topic is not None:
108  self.setTitle(menu_topic)
109  self._menu_topic = menu_topic
110  else:
111  self._menu_topic = None
112 
113  self._reset_timeline = self.addAction('Reset Timeline')
114 
115  self._play_all = self.addAction('Play All Messages')
116  self._play_all.setCheckable(True)
117  self._play_all.setChecked(self.timeline.play_all)
118 
119  self.addSeparator()
120 
121  self._renderers = self.timeline._timeline_frame.get_renderers()
123 
124  # create thumbnail menu items
125  if menu_topic is None:
126  submenu = self.addMenu('Thumbnails...')
127  self._thumbnail_show_action = submenu.addAction('Show All')
128  self._thumbnail_hide_action = submenu.addAction('Hide All')
129  submenu.addSeparator()
130 
131  for topic, renderer in self._renderers:
132  self._thumbnail_actions.append(submenu.addAction(topic))
133  self._thumbnail_actions[-1].setCheckable(True)
134  self._thumbnail_actions[-1].setChecked(
135  self.timeline._timeline_frame.is_renderer_active(topic))
136  else:
137  self._thumbnail_show_action = None
138  self._thumbnail_hide_action = None
139  for topic, renderer in self._renderers:
140  if menu_topic == topic:
141  self._thumbnail_actions.append(self.addAction("Thumbnail"))
142  self._thumbnail_actions[-1].setCheckable(True)
143  self._thumbnail_actions[-1].setChecked(
144  self.timeline._timeline_frame.is_renderer_active(topic))
145 
146  # create view menu items
147  self._topic_actions = []
148  self._type_actions = []
149  if menu_topic is None:
150  self._topics = self.timeline._timeline_frame.topics
151  view_topics_menu = self.addMenu('View (by Topic)')
152  for topic in self._topics:
153  datatype = self.timeline.get_datatype(topic)
154 
155  # View... / topic
156  topic_menu = QMenu(topic, self)
157  viewer_types = self.timeline._timeline_frame.get_viewer_types(datatype)
158 
159  # View... / topic / Viewer
160  for viewer_type in viewer_types:
161  tempaction = topic_menu.addAction(viewer_type.name)
162  tempaction.setData(viewer_type)
163  self._topic_actions.append(tempaction)
164  view_topics_menu.addMenu(topic_menu)
165 
166  view_type_menu = self.addMenu('View (by Type)')
167  self._topics_by_type = self.timeline._timeline_frame._topics_by_datatype
168  for datatype in self._topics_by_type:
169  # View... / datatype
170  datatype_menu = QMenu(datatype, self)
171  datatype_topics = self._topics_by_type[datatype]
172  viewer_types = self.timeline._timeline_frame.get_viewer_types(datatype)
173  for topic in [t for t in self._topics if t in datatype_topics]: # use timeline ordering
174  topic_menu = QMenu(topic, datatype_menu)
175  # View... / datatype / topic / Viewer
176  for viewer_type in viewer_types:
177  tempaction = topic_menu.addAction(viewer_type.name)
178  tempaction.setData(viewer_type)
179  self._topic_actions.append(tempaction)
180  datatype_menu.addMenu(topic_menu)
181  view_type_menu.addMenu(datatype_menu)
182  else:
183  view_menu = self.addMenu("View")
184  datatype = self.timeline.get_datatype(menu_topic)
185 
186  viewer_types = self.timeline._timeline_frame.get_viewer_types(datatype)
187  for viewer_type in viewer_types:
188  tempaction = view_menu.addAction(viewer_type.name)
189  tempaction.setData(viewer_type)
190  self._topic_actions.append(tempaction)
191 
192  self.addSeparator()
193 
194  # create publish menu items
196  if menu_topic is None:
197  submenu = self.addMenu('Publish...')
198 
199  self._publish_all = submenu.addAction('Publish All')
200  self._publish_none = submenu.addAction('Publish None')
201 
202  submenu.addSeparator()
203 
204  for topic in self._topics:
205  self._publish_actions.append(submenu.addAction(topic))
206  self._publish_actions[-1].setCheckable(True)
207  self._publish_actions[-1].setChecked(self.timeline.is_publishing(topic))
208  else:
209  self._publish_actions.append(self.addAction("Publish"))
210  self._publish_actions[-1].setCheckable(True)
211  self._publish_actions[-1].setChecked(self.timeline.is_publishing(menu_topic))
212  self._publish_all = None
213  self._publish_none = None
214 
215  action = self.exec_(event.globalPos())
216  if action is not None and action != 0:
217  self.process(action)
218 
219  def process(self, action):
220  """
221  :param action: action to execute, ''QAction''
222  :raises: when it doesn't recognice the action passed in, ''Exception''
223  """
224  if action == self._reset_timeline:
225  self.timeline._timeline_frame.reset_timeline()
226  elif action == self._play_all:
227  self.timeline.toggle_play_all()
228  elif action == self._publish_all:
229  for topic in self.timeline._timeline_frame.topics:
230  if not self.timeline.start_publishing(topic):
231  break
232  elif action == self._publish_none:
233  for topic in self.timeline._timeline_frame.topics:
234  if not self.timeline.stop_publishing(topic):
235  break
236  elif action == self._thumbnail_show_action:
237  self.timeline._timeline_frame.set_renderers_active(True)
238  elif action == self._thumbnail_hide_action:
239  self.timeline._timeline_frame.set_renderers_active(False)
240  elif action in self._thumbnail_actions:
241  if self._menu_topic is None:
242  topic = action.text()
243  else:
244  topic = self._menu_topic
245 
246  if self.timeline._timeline_frame.is_renderer_active(topic):
247  self.timeline._timeline_frame.set_renderer_active(topic, False)
248  else:
249  self.timeline._timeline_frame.set_renderer_active(topic, True)
250  elif action in self._topic_actions + self._type_actions:
251  if self._menu_topic is None:
252  topic = action.parentWidget().title()
253  else:
254  topic = self._menu_topic
255 
256  popup_name = topic + '__' + action.text()
257  if popup_name not in self.timeline.popups:
258  frame = TopicPopupWidget(popup_name, self.timeline,
259  action.data(), str(topic))
260 
261  self.timeline.add_view(topic, frame)
262  self.timeline.popups[popup_name] = frame
263 
264  # make popup visible
265  frame = self.timeline.popups[popup_name]
266  frame.show(self.timeline.get_context())
267 
268  elif action in self._publish_actions:
269  if self._menu_topic is None:
270  topic = action.text()
271  else:
272  topic = self._menu_topic
273 
274  if self.timeline.is_publishing(topic):
275  self.timeline.stop_publishing(topic)
276  else:
277  self.timeline.start_publishing(topic)
278  else:
279  raise Exception('Unknown action in TimelinePopupMenu.process')
def __init__(self, popup_name, timeline, viewer_type, topic)
def __init__(self, timeline, event, menu_topic)


rqt_bag
Author(s): Dirk Thomas , Aaron Blasdel , Austin Hendrix , Tim Field
autogenerated on Fri Feb 19 2021 03:14:14