util.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 import os
34 
35 import rospy
36 
37 from python_qt_binding.QtGui import QIcon, QImage, QPainter, QPixmap
38 from python_qt_binding.QtWidgets import QMessageBox
39 from python_qt_binding.QtSvg import QSvgRenderer
40 
41 
42 def dashinfo(msg, obj, title='Info'):
43  """
44  Logs a message with ``rospy.loginfo`` and displays a ``QMessageBox`` to the user
45 
46  :param msg: Message to display.
47  :type msg: str
48  :param obj: Parent object for the ``QMessageBox``
49  :type obj: QObject
50  :param title: An optional title for the `QMessageBox``
51  :type title: str
52  """
53  rospy.loginfo(msg)
54 
55  box = QMessageBox()
56  box.setText(msg)
57  box.setWindowTitle(title)
58  box.show()
59 
60  obj._message_box = box
61 
62 
63 def dashwarn(msg, obj, title='Warning'):
64  """
65  Logs a message with ``rospy.logwarn`` and displays a ``QMessageBox`` to the user
66 
67  :param msg: Message to display.
68  :type msg: str
69  :param obj: Parent object for the ``QMessageBox``
70  :type obj: QObject
71  :param title: An optional title for the `QMessageBox``
72  :type title: str
73  """
74  rospy.logwarn(msg)
75 
76  box = QMessageBox()
77  box.setText(msg)
78  box.setWindowTitle(title)
79  box.show()
80 
81  obj._message_box = box
82 
83 
84 def dasherr(msg, obj, title='Error'):
85  """
86  Logs a message with ``rospy.logerr`` and displays a ``QMessageBox`` to the user
87 
88  :param msg: Message to display.
89  :type msg: str
90  :param obj: Parent object for the ``QMessageBox``
91  :type obj: QObject
92  :param title: An optional title for the `QMessageBox``
93  :type title: str
94  """
95  rospy.logerr(msg)
96 
97  box = QMessageBox()
98  box.setText(msg)
99  box.setWindowTitle(title)
100  box.show()
101 
102  obj._message_box = box
103 
104 
105 class IconHelper(object):
106  """
107  Helper class to easily access images and build QIcons out of lists of file names
108  """
109  def __init__(self, paths=None, name="IconHelper"):
110  self._image_paths = paths if paths else []
111  self._name = name
112 
113  def add_image_path(self, path):
114  """
115  Paths added will be searched for images by the _find_image function
116  Paths will be searched in revearse order by add time
117  The last path to be searched is always rqt_robot_dashboard/images
118  Subdirectories are not recursively searched
119 
120  :param path: The path to add to the image paths list
121  :type path: str
122  """
123  self._image_paths = [path] + self._image_paths
124 
125  def make_icon(self, image_list, mode=QIcon.Normal, state=QIcon.On):
126  """
127  Helper function to create QIcons from lists of image files
128  Warning: svg files interleaved with other files will not render correctly
129 
130  :param image_list: list of image paths to layer into an icon.
131  :type image: list of str
132  :param mode: The mode of the QIcon to be created.
133  :type mode: int
134  :param state: the state of the QIcon to be created.
135  :type state: int
136  """
137  if type(image_list) is not list:
138  image_list = [image_list]
139  if len(image_list) <= 0:
140  raise TypeError('The list of images is empty.')
141 
142  num_svg = 0
143  for item in image_list:
144  if item[-4:].lower() == '.svg':
145  num_svg = num_svg + 1
146 
147  if num_svg != len(image_list):
148  # Legacy support for non-svg images
149  icon_pixmap = QPixmap()
150  icon_pixmap.load(image_list[0])
151  painter = QPainter(icon_pixmap)
152  for item in image_list[1:]:
153  painter.drawPixmap(0, 0, QPixmap(item))
154  icon = QIcon()
155  icon.addPixmap(icon_pixmap, mode, state)
156  painter.end()
157  return icon
158  else:
159  # rendering SVG files into a QImage
160  renderer = QSvgRenderer(image_list[0])
161  icon_image = QImage(renderer.defaultSize(), QImage.Format_ARGB32)
162  icon_image.fill(0)
163  painter = QPainter(icon_image)
164  renderer.render(painter)
165  if len(image_list) > 1:
166  for item in image_list[1:]:
167  renderer.load(item)
168  renderer.render(painter)
169  painter.end()
170  # Convert QImage into a pixmap to create the icon
171  icon_pixmap = QPixmap()
172  icon_pixmap.convertFromImage(icon_image)
173  icon = QIcon(icon_pixmap)
174  return icon
175 
176  def find_image(self, path):
177  """
178  Convenience function to help with finding images.
179  Path can either be specified as absolute paths or relative to any path in ``_image_paths``
180 
181  :param path: The path or name of the image.
182  :type path: str
183  """
184  if os.path.exists(path):
185  return path
186  for image_path in self._image_paths:
187  if os.path.exists(os.path.join(image_path, path)):
188  return os.path.join(image_path, path)
189  elif '.' in path and os.path.exists(os.path.join(image_path, 'nonsvg', path)):
190  return os.path.join(image_path, 'nonsvg', path)
191  return os.path.join(self._image_paths[-1], 'ic-missing-icon.svg')
192 
193  def build_icon(self, image_name_list, mode=QIcon.Normal, state=QIcon.On):
194  """
195  Convenience function to create an icon from a list of file names
196 
197  :param image_name_list: List of file image names to make into an icon
198  :type image_name_list: list of str
199  :param mode: The mode of the QIcon to be created.
200  :type mode: int
201  :param state: the state of the QIcon to be created.
202  :type state: int
203  """
204  found_list = []
205  for name in image_name_list:
206  found_list.append(self.find_image(name))
207  return self.make_icon(found_list, mode, state)
208 
209  def set_icon_lists(self, icons, clicked_icons=None, suppress_overlays=False):
210  """
211  Sets up the icon lists for the button states.
212  There must be one index in icons for each state.
213 
214  :raises IndexError: if ``icons`` is not a list of lists of strings
215 
216  :param icons: A list of lists of strings to create icons for the states of this button.\
217  If only one is supplied then ok, warn, error, stale icons will be created with overlays
218  :type icons: list
219  :param clicked_icons: A list of clicked state icons. len must equal icons
220  :type clicked_icons: list
221  :param suppress_overlays: if false and there is only one icon path supplied
222  :type suppress_overlays: bool
223  """
224  if clicked_icons is not None and len(icons) != len(clicked_icons):
225  rospy.logerr("%s: icons and clicked states are unequal" % self._name)
226  icons = clicked_icons = [['ic-missing-icon.svg']]
227  if not (type(icons) is list and type(icons[0]) is list and type(icons[0][0] is str)):
228  raise(IndexError("icons must be a list of lists of strings"))
229  if len(icons) <= 0:
230  rospy.logerr("%s: Icons not supplied" % self._name)
231  icons = clicked_icons = ['ic-missing-icon.svg']
232  if len(icons) == 1 and suppress_overlays == False:
233  if icons[0][0][-4].lower() == '.svg':
234  icons.append(icons[0] + ['ol-warn-badge.svg'])
235  icons.append(icons[0] + ['ol-err-badge.svg'])
236  icons.append(icons[0] + ['ol-stale-badge.svg'])
237  else:
238  icons.append(icons[0] + ['warn-overlay.png'])
239  icons.append(icons[0] + ['err-overlay.png'])
240  icons.append(icons[0] + ['stale-overlay.png'])
241  if clicked_icons is None:
242  clicked_icons = []
243  for name in icons:
244  clicked_icons.append(name + ['ol-click.svg'])
245  icons_conv = []
246  for icon in icons:
247  icons_conv.append(self.build_icon(icon))
248  clicked_icons_conv = []
249  for icon in clicked_icons:
250  clicked_icons_conv.append(self.build_icon(icon))
251  return (icons_conv, clicked_icons_conv)
def __init__(self, paths=None, name="IconHelper")
Definition: util.py:109
def set_icon_lists(self, icons, clicked_icons=None, suppress_overlays=False)
Definition: util.py:209
def dasherr(msg, obj, title='Error')
Definition: util.py:84
def find_image(self, path)
Definition: util.py:176
def make_icon(self, image_list, mode=QIcon.Normal, state=QIcon.On)
Definition: util.py:125
def dashinfo(msg, obj, title='Info')
Definition: util.py:42
def dashwarn(msg, obj, title='Warning')
Definition: util.py:63
def add_image_path(self, path)
Definition: util.py:113
def build_icon(self, image_name_list, mode=QIcon.Normal, state=QIcon.On)
Definition: util.py:193


rqt_robot_dashboard
Author(s): Ze'ev Klapow
autogenerated on Mon Feb 28 2022 23:38:55