parameter_tree_widget.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import rospy
4 import actionlib
5 import std_msgs.msg
6 import vigir_footstep_planning_msgs.msg
7 
8 from python_qt_binding.QtCore import Qt, QPoint, QModelIndex, Slot
9 from python_qt_binding.QtGui import QWidget, QTreeWidget, QTreeWidgetItem, QMenu, QAction, QAbstractItemView, QColor, QIcon
10 
11 from vigir_generic_params.msg import ParameterSetMsg
14 
15 
16 class QParameterTreeWidget(QTreeWidget):
17 
18  logger = Logger()
19 
20  def __init__(self, parent=None, logger=Logger()):
21  QTreeWidget.__init__(self, parent)
22  self.set_logger(logger)
23 
24  # init tree
25  self.setHeaderLabels(["Name", "Type", "Value"])
26  self.sortItems(0, Qt.AscendingOrder)
27  #self.setSelectionMode(QAbstractItemView.NoSelection)
28  self.setContextMenuPolicy(Qt.CustomContextMenu)
29  self.itemActivated.connect(self.edit_item)
30  self.currentItemChanged.connect(self.current_item_changed)
31 
32  # context menu
33  self.customContextMenuRequested.connect(self.context_menu_request)
34  self._action_item_expand = QAction(QIcon.fromTheme('zoom-in'), 'Expand Selected', self)
35  self._action_item_expand.triggered.connect(self._handle_action_item_expand)
36  self._action_item_collapse = QAction(QIcon.fromTheme('zoom-out'), 'Collapse Selected', self)
37  self._action_item_collapse.triggered.connect(self._handle_action_item_collapse)
38  self._action_item_add = QAction(QIcon.fromTheme('list-add'), 'Add', self)
39  self._action_item_add.setEnabled(False) # TODO
40  self._action_item_remove = QAction(QIcon.fromTheme('list-remove'), 'Remove', self)
41  self._action_item_remove.setEnabled(False) # TODO
42 
43  def set_logger(self, logger):
44  self.logger = logger
45 
46  @Slot(QPoint)
47  def context_menu_request(self, point):
48  if self.selectionModel().hasSelection():
49  menu = QMenu(self)
50  menu.addAction(self._action_item_add)
51  menu.addAction(self._action_item_remove)
52  menu.addSeparator()
53  menu.addAction(self._action_item_expand)
54  menu.addAction(self._action_item_collapse)
55  menu.exec_(self.mapToGlobal(point))
56 
57  @Slot()
59  self._handle_action_set_expanded(False)
60 
61  @Slot()
64 
65  @Slot(bool)
66  def _handle_action_set_expanded(self, expanded):
67  def recursive_set_expanded(index):
68  if (index != QModelIndex()) and (index.column() == 0):
69  self.setExpanded(index, expanded)
70  #for i in range(index.model().childCount()):
71  # index.model().child(i).setExpanded(expanded)
72  #for i in range(index.model().rowCount()):
73  # recursive_set_expanded(index.child(i, 0))
74 
75  for index in self.selectedIndexes():
76  recursive_set_expanded(index)
77 
78  @Slot(QTreeWidgetItem, int)
79  def edit_item(self, item, column):
80  if (column == 0) or (item.is_leaf() and (column == 2)):
81  item.setFlags(item.flags() | Qt.ItemIsEditable)
82  self.editItem(item, column)
83  item.setFlags(item.flags() & ~Qt.ItemIsEditable)
84 
85  @Slot(QTreeWidgetItem, QTreeWidgetItem)
86  def current_item_changed(self, prev, current):
87  if prev is not None:
88  if not prev.update_value():
89  self.logger.log_error("Couldn't update value for '" + prev.get_name() + "' in '" + prev.get_namespace() + "'. Check input syntax!")
90  if current is not None:
91  if not current.update_value():
92  self.logger.log_error("Couldn't update value for '" + current.get_name() + "' in '" + current.get_namespace() + "'. Check input syntax!")
93 
94  # set parameter set from msg
95  def set_parameter_set(self, param_set_msg):
96  self.clear()
97 
98  self.root = QParameterTreeWidgetItem(self, self.logger, name=param_set_msg.name.data)
99  self.root.setExpanded(True)
100 
101  for p in param_set_msg.params:
102  self.root.add_param(Parameter(msg=p))
103 
104  # get parameter set as msg
105  def get_parameter_set(self):
106  params = self.root.get_params()
107 
108  # remove top-level namespace
109  top_len = len(self.root.get_name()) + 2
110  for p in params:
111  p.set_name(p.get_name()[top_len:])
112 
113  # generate msg
114  param_set_msg = ParameterSet()
115  param_set_msg.name.data = self.root.get_name()
116  for p in params:
117  param_set_msg.parameters.append(p.to_msg())
118 
119  return param_set_msg
120 
121 
122 class QParameterTreeWidgetItem(QTreeWidgetItem):
123 
124  logger = Logger()
125  param = None
126  namespace = str()
127 
128  def __init__(self, parent=None, logger=Logger(), param = None, name=str(), namespace=str()):
129  QTreeWidgetItem.__init__(self, parent)
130  self.set_logger(logger)
131 
132  if param is not None:
133  self.set_param(param)
134  elif len(name) > 0:
135  self.set_name(name)
136  self.namespace = namespace
137 
138  def set_logger(self, logger):
139  self.logger = logger
140 
141  def is_leaf(self):
142  return self.param is not None
143 
144  def update_value(self):
145  result = True
146  if self.is_leaf():
147  self.param.set_name(self.text(0))
148  result = self.param.set_value(self.text(2))
149  #self.setText(2, str(self.param.get_value()))
150  if result:
151  for i in range(self.columnCount()):
152  self.setBackgroundColor(i, Qt.white)
153  else:
154  for i in range(self.columnCount()):
155  self.setBackgroundColor(i, QColor(255, 165, 0))
156  return result
157 
158  def set_name(self, name):
159  self.setText(0, name)
160  if self.is_leaf():
161  self.param.set_name(name)
162 
163  def get_name(self):
164  return self.text(0)
165 
166  def get_namespace(self):
167  return self.namespace
168 
169  def set_param(self, param, namespace = str()):
170  self.param = param
171  self.namespace = namespace
172  if self.is_leaf():
173  self.setText(0, self.param.get_name())
174  self.setText(1, str(self.param.get_type_as_text()))
175  self.setText(2, str(self.param.get_value()))
176 
177  def get_param(self):
178  return self.param
179 
180  def get_params(self):
181  params = []
182  if self.is_leaf():
183  # sync with recent changes from UI
184  if not self.update_value():
185  self.logger.log_warn("Value for '" + self.get_name() + "' in '" + self.get_namespace() + "' has invalid changes. Check input syntax!")
186 
187  p = self.get_param()
188  p.set_name(self.get_namespace() + '/' + p.get_name())
189  params.append(p)
190  else:
191  for i in range(self.childCount()):
192  params.extend(self.child(i).get_params())
193  return params
194 
195  # adds param recursively (based on namespace)
196  def add_param(self, param):
197  # finds branch matching the name
198  def find_branch(name):
199  for i in range(self.childCount()):
200  if self.child(i).text(0) == name:
201  return self.child(i)
202  return None
203 
204  # adds param to existing branch or create new branch recursively
205  def add_param_to_branch(param, branch_name):
206  branch = find_branch(branch_name)
207  if branch is None:
208  branch = QParameterTreeWidgetItem(self, self.logger, name = branch_name, namespace = self.get_namespace() + '/' + self.get_name())
209  branch.add_param(param)
210 
211  if self.is_leaf():
212  print "Error: Can't add parameter '" + param.get_name() + "' to the leaf '" + self.get_name() + "'!"
213  return
214 
215  # check if param has namespace
216  param.set_name(param.get_name().strip('/'))
217  i = param.get_name().find('/')
218 
219  # add as leaf
220  if i == -1:
221  QParameterTreeWidgetItem(self, self.logger, param, namespace = self.get_namespace() + '/' + self.get_name())
222  # add into branch
223  else:
224  branch_name = param.get_name()[:i]
225  param.set_name(param.get_name()[i+1:])
226  add_param_to_branch(param, branch_name)
def __init__(self, parent=None, logger=Logger(), param=None, name=str(), namespace=str())
std::string & strip(std::string &s, const char c)
Definition: helper.h:153


vigir_footstep_planning_lib
Author(s): Alexander Stumpf
autogenerated on Mon Jun 10 2019 15:47:33