paramedit_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 # Author: Isaac Saito, Ze'ev Klapow
00034 
00035 import os
00036 from collections import OrderedDict
00037 
00038 import dynamic_reconfigure.client
00039 from python_qt_binding import loadUi
00040 from python_qt_binding.QtCore import Qt, Signal
00041 from python_qt_binding.QtWidgets import QVBoxLayout, QWidget, QWidgetItem
00042 from rqt_py_common.layout_util import LayoutUtil
00043 import rospy
00044 
00045 from .dynreconf_client_widget import DynreconfClientWidget
00046 
00047 
00048 class ParameditWidget(QWidget):
00049     """
00050     This class represents a pane where parameter editor widgets of multiple
00051     nodes are shown. In rqt_reconfigure, this pane occupies right half of the
00052     entire visible area.
00053     """
00054 
00055     # public signal
00056     sig_node_disabled_selected = Signal(str)
00057 
00058     def __init__(self, rospack):
00059         """"""
00060         super(ParameditWidget, self).__init__()
00061 
00062         ui_file = os.path.join(rospack.get_path('rqt_reconfigure'),
00063                                'resource', 'paramedit_pane.ui')
00064         loadUi(ui_file, self, {'ParameditWidget': ParameditWidget})
00065 
00066         self._dynreconf_clients = OrderedDict()
00067 
00068         # Adding the list of Items
00069         self.vlayout = QVBoxLayout(self.scrollarea_holder_widget)
00070 
00071         #self._set_index_widgets(self.listview, paramitems_dict) # causes error
00072         self.destroyed.connect(self.close)
00073 
00074     def _set_index_widgets(self, view, paramitems_dict):
00075         """
00076         @deprecated: Causes error
00077         """
00078         i = 0
00079         for p in paramitems_dict:
00080             view.setIndexWidget(i, p)
00081             i += 1
00082 
00083     def show_reconf(self, dynreconf_widget):
00084         """
00085         Callback when user chooses a node.
00086 
00087         @param dynreconf_widget:
00088         """
00089         node_grn = dynreconf_widget.get_node_grn()
00090         rospy.logdebug('ParameditWidget.show str(node_grn)=%s', str(node_grn))
00091 
00092         if not node_grn in self._dynreconf_clients.keys():
00093             # Add dynreconf widget if there isn't already one.
00094 
00095             # Client gets renewed every time different node_grn was clicked.
00096 
00097             self._dynreconf_clients.__setitem__(node_grn, dynreconf_widget)
00098             self.vlayout.addWidget(dynreconf_widget)
00099             dynreconf_widget.sig_node_disabled_selected.connect(
00100                                                            self._node_disabled)
00101 
00102         else:  # If there has one already existed, remove it.
00103             self._remove_node(node_grn)
00104             #LayoutUtil.clear_layout(self.vlayout)
00105 
00106             # Re-add the rest of existing items to layout.
00107             #for k, v in self._dynreconf_clients.items():
00108             #    rospy.loginfo('added to layout k={} v={}'.format(k, v))
00109             #    self.vlayout.addWidget(v)
00110 
00111         # Add color to alternate the rim of the widget.
00112         LayoutUtil.alternate_color(
00113             self._dynreconf_clients.values(),
00114             [self.palette().window().color().lighter(125),
00115              self.palette().window().color().darker(125)])
00116 
00117     def close(self):
00118         for dc in self._dynreconf_clients:
00119             # Clear out the old widget
00120             dc.close()
00121             dc = None
00122 
00123             self._paramedit_scrollarea.deleteLater()
00124 
00125     def filter_param(self, filter_key):
00126         """
00127         :type filter_key:
00128         """
00129 
00130         #TODO Pick nodes that match filter_key.
00131 
00132         #TODO For the nodes that are kept in previous step, call
00133         #     DynreconfWidget.filter_param for all of its existing
00134         #     instances.
00135         pass
00136 
00137     def _remove_node(self, node_grn):
00138         try:
00139             i = self._dynreconf_clients.keys().index(node_grn)
00140         except ValueError:
00141             # ValueError occurring here means that the specified key is not
00142             # found, most likely already removed, which is possible in the
00143             # following situation/sequence:
00144             #
00145             # Node widget on ParameditWidget removed by clicking disable button
00146             # --> Node deselected on tree widget gets updated
00147             # --> Tree widget detects deselection
00148             # --> Tree widget emits deselection signal, which is captured by
00149             #     ParameditWidget's slot. Thus reaches this method again.
00150             return
00151 
00152         item = self.vlayout.itemAt(i)
00153         if isinstance(item, QWidgetItem):
00154                 item.widget().close()
00155         w = self._dynreconf_clients.pop(node_grn)
00156 
00157         rospy.logdebug('popped={} Len of left clients={}'.format(
00158                                             w, len(self._dynreconf_clients)))
00159 
00160     def _node_disabled(self, node_grn):
00161         rospy.logdebug('paramedit_w _node_disabled grn={}'.format(node_grn))
00162 
00163         # Signal to notify other GUI components (eg. nodes tree pane) that
00164         # a node widget is disabled.
00165         self.sig_node_disabled_selected.emit(node_grn)
00166 
00167         # Remove the selected node widget from the internal list of nodes.
00168         self._remove_node(node_grn)


rqt_reconfigure
Author(s): Isaac Saito, Ze'ev Klapow
autogenerated on Sat Jul 15 2017 02:25:06