Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 from __future__ import division
00036
00037 import os
00038 import sys
00039
00040 import dynamic_reconfigure as dyn_reconf
00041 from python_qt_binding import loadUi
00042 from python_qt_binding.QtCore import Qt, QTimer, Signal
00043 from python_qt_binding.QtGui import QStandardItemModel, QWidget
00044 import rospy
00045 import rosservice
00046
00047 from .parameter_item import ParameterItem
00048
00049 class NodeSelectorWidget(QWidget):
00050 _COL_NAMES = ['Node']
00051
00052
00053 sig_node_selected = Signal(str)
00054
00055 def __init__(self):
00056 super(NodeSelectorWidget, self).__init__()
00057 self.stretch = None
00058
00059 ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
00060 'ui/node_selector.ui')
00061 loadUi(ui_file, self)
00062
00063
00064 self._std_model = QStandardItemModel()
00065 self._node_selector_view.setModel(self._std_model)
00066 self._rootitem = self._std_model.invisibleRootItem()
00067
00068 self._nodes_previous = None
00069
00070
00071
00072 self._update_nodetree()
00073
00074
00075 selectionModel = self._node_selector_view.selectionModel()
00076 selectionModel.selectionChanged.connect(self._selection_changed_slot)
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 self._collapse_button.pressed.connect(self._node_selector_view.collapseAll)
00087 self._expand_button.pressed.connect(self._node_selector_view.expandAll)
00088
00089 def _selection_changed_slot(self, selected, deselected):
00090 """
00091 Overriden from QItemSelectionModel.
00092
00093 :type new_item_select: QItemSelection
00094 :type old_item_select: QItemSelection
00095 """
00096
00097 index_current = self._node_selector_view.selectionModel().currentIndex()
00098 rospy.logdebug('_selection_changed_slot row=%d col=%d data=%s ' +
00099 'data.parent=%s child(0, 0)=%s',
00100 index_current.row(),
00101 index_current.column(),
00102 index_current.data(Qt.DisplayRole),
00103 index_current.parent().data(Qt.DisplayRole),
00104 index_current.child(0, 0).data(Qt.DisplayRole))
00105
00106 if not index_current.child(0, 0).data(Qt.DisplayRole) == None:
00107 return
00108
00109
00110 node_name_selected = self.get_full_grn_recur(index_current, '')
00111 rospy.logdebug('_selection_changed_slot node_name_selected=%s',
00112 node_name_selected)
00113 self.sig_node_selected.emit(node_name_selected)
00114
00115 def get_full_grn_recur(self, model_index, str_grn):
00116 """
00117
00118 Create full path format of GRN (Graph Resource Names, see
00119 http://www.ros.org/wiki/Names).
00120
00121 An example: /wide_stereo/left/image_color/compressed
00122
00123 Bulid GRN by recursively transcending parents & children of
00124 QModelIndex instance.
00125
00126 Upon its very 1st call, the argument is the index where user clicks on on
00127 the view object (here QTreeView is used but should work with other View).
00128 str_grn can be 0-length string.
00129
00130 :type model_index: QModelIndex
00131 :type str_grn: str
00132 :param str_grn: This could be an incomplete or a complete GRN format.
00133 """
00134
00135
00136 rospy.logdebug('get_full_grn_recur in str=%s', str_grn)
00137 if model_index.data(Qt.DisplayRole) == None:
00138 return str_grn
00139 str_grn = '/' + str(model_index.data(Qt.DisplayRole)) + str_grn
00140 rospy.logdebug('get_full_grn_recur out str=%s', str_grn)
00141 return self.get_full_grn_recur(model_index.parent(), str_grn)
00142
00143 def _update_nodetree(self):
00144 """
00145 """
00146
00147
00148
00149
00150 try:
00151 nodes = dyn_reconf.find_reconfigure_services()
00152 except rosservice.ROSServiceIOException as e:
00153 rospy.logerr("Reconfigure GUI cannot connect to master.")
00154 raise e
00155
00156 if not nodes == self._nodes_previous:
00157 paramname_prev = ''
00158 paramitem_top_prev = None
00159 i_debug = 0
00160 for node_name_grn in nodes:
00161 p = ParameterItem(node_name_grn)
00162 p.set_param_name(node_name_grn)
00163 names = p.get_param_names()
00164
00165 i_debug += 1
00166 rospy.logdebug('_update_nodetree i=%d names=%s',
00167 i_debug, names)
00168
00169 self._add_tree_node(p, self._rootitem, names)
00170
00171 def _add_tree_node(self, param_item_full, stditem_parent, child_names_left):
00172 """
00173
00174 Evaluate current node and the previous node on the same depth.
00175 If the name of both nodes is the same, current node instance is ignored.
00176 If not, the current node gets added to the same parent node.
00177 At the end, this function gets called recursively going down 1 level.
00178
00179 :type param_item_full: ParameterItem
00180 :type stditem_parent: QStandardItem.
00181 :type child_names_left: List of str
00182 :param child_names_left: List of strings that is sorted in hierarchical
00183 order of params.
00184 """
00185
00186
00187 name_curr = child_names_left.pop(0)
00188 stditem_curr = ParameterItem(param_item_full.get_raw_param_name())
00189
00190
00191 row_index_parent = stditem_parent.rowCount() - 1
00192
00193
00194 name_prev = ''
00195 stditem_prev = None
00196 if not stditem_parent.child(row_index_parent) == None:
00197 stditem_prev = stditem_parent.child(row_index_parent)
00198 name_prev = stditem_prev.text()
00199
00200 stditem = None
00201 if name_prev != name_curr:
00202 stditem_curr.setText(name_curr)
00203 stditem_parent.appendRow(stditem_curr)
00204 stditem = stditem_curr
00205 else:
00206 stditem = stditem_prev
00207
00208 rospy.logdebug('add_tree_node 1 name_curr=%s ' +
00209 '\n\t\t\t\t\tname_prev=%s row_index_parent=%d',
00210 name_curr, name_prev, row_index_parent)
00211
00212 if len(child_names_left) != 0:
00213
00214
00215
00216 self._add_tree_node(param_item_full, stditem, child_names_left)
00217
00218 def _refresh_nodes(self):
00219
00220
00221
00222 model = self._rootitem
00223 if model.hasChildren():
00224 row_count = model.rowCount()
00225 model.removeRows(0, row_count)
00226 rospy.logdebug("ParamWidget _refresh_nodes row_count=%s", row_count)
00227 self._update_nodetree()
00228
00229 def close_node(self):
00230 rospy.logdebug(" in close_node")
00231