publisher_tree_model.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright (c) 2011, Dorian Scholz, TU Darmstadt
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 the TU Darmstadt 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 HOLDER 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 import threading
33 
34 from python_qt_binding.QtCore import Qt, Signal
35 from python_qt_binding.QtGui import QStandardItem, QStandardItemModel
36 
37 from rqt_py_common.message_tree_model import MessageTreeModel
38 from rqt_py_common.data_items import ReadonlyItem, CheckableItem
39 
40 
42  _column_names = ['topic', 'type', 'rate', 'expression']
43  item_value_changed = Signal(int, str, str, str, object)
44 
45  def __init__(self, parent=None):
46  super(PublisherTreeModel, self).__init__(parent)
47  self._column_index = {}
48  for column_name in self._column_names:
49  self._column_index[column_name] = len(self._column_index)
50  self.clear()
51 
52  self._item_change_lock = threading.Lock()
53  self.itemChanged.connect(self.handle_item_changed)
54 
55  def clear(self):
56  super(PublisherTreeModel, self).clear()
57  self.setHorizontalHeaderLabels(self._column_names)
58 
59  def get_publisher_ids(self, index_list):
60  return [item._user_data['publisher_id'] for item in self._get_toplevel_items(index_list)]
61 
62  def remove_items_with_parents(self, index_list):
63  for item in self._get_toplevel_items(index_list):
64  self.removeRow(item.row())
65 
66  def handle_item_changed(self, item):
67  if not self._item_change_lock.acquire(False):
68  # qDebug('PublisherTreeModel.handle_item_changed(): could not acquire lock')
69  return
70  # lock has been acquired
71  topic_name = item._path
72  column_name = self._column_names[item.column()]
73  if item.isCheckable():
74  new_value = str(item.checkState() == Qt.Checked)
75  else:
76  new_value = item.text().strip()
77  # print 'PublisherTreeModel.handle_item_changed(): %s, %s, %s' %
78  # (topic_name, column_name, new_value)
79 
80  self.item_value_changed.emit(
81  item._user_data['publisher_id'], topic_name, column_name, new_value, item.setText)
82 
83  # release lock
84  self._item_change_lock.release()
85 
86  def remove_publisher(self, publisher_id):
87  for top_level_row_number in range(self.rowCount()):
88  item = self.item(top_level_row_number)
89  if item is not None and item._user_data['publisher_id'] == publisher_id:
90  self.removeRow(top_level_row_number)
91  return top_level_row_number
92  return None
93 
94  def update_publisher(self, publisher_info):
95  top_level_row_number = self.remove_publisher(publisher_info['publisher_id'])
96  self.add_publisher(publisher_info, top_level_row_number)
97 
98  def add_publisher(self, publisher_info, top_level_row_number=None):
99  # recursively create widget items for the message's slots
100  parent = self
101  slot = publisher_info['message_instance']
102  slot_name = publisher_info['topic_name']
103  slot_type_name = publisher_info['message_instance']._type
104  slot_path = publisher_info['topic_name']
105  user_data = {'publisher_id': publisher_info['publisher_id']}
106  kwargs = {
107  'user_data': user_data,
108  'top_level_row_number': top_level_row_number,
109  'expressions': publisher_info['expressions'],
110  }
111  top_level_row = self._recursive_create_items(
112  parent, slot, slot_name, slot_type_name, slot_path, **kwargs)
113 
114  # fill tree widget columns of top level item
115  if publisher_info['enabled']:
116  top_level_row[self._column_index['topic']].setCheckState(Qt.Checked)
117  top_level_row[self._column_index['rate']].setText(str(publisher_info['rate']))
118 
119  def _get_data_items_for_path(self, slot_name, slot_type_name, slot_path, **kwargs):
120  if slot_name.startswith('/'):
121  return (CheckableItem(slot_name),
122  ReadonlyItem(slot_type_name),
123  QStandardItem(''),
124  ReadonlyItem(''))
125  expression_item = QStandardItem('')
126  expression_item.setToolTip(
127  'enter valid Python expression here, using "i" as counter and functions from math, '
128  'random and time modules')
129  return (ReadonlyItem(slot_name),
130  QStandardItem(slot_type_name),
131  ReadonlyItem(''),
132  expression_item)
133 
135  self, parent, slot, slot_name, slot_type_name, slot_path, expressions={}, **kwargs):
136  row, is_leaf_node = super(PublisherTreeModel, self)._recursive_create_items(
137  parent, slot, slot_name, slot_type_name, slot_path, expressions=expressions, **kwargs)
138  if is_leaf_node:
139  expression_text = expressions.get(slot_path, repr(slot))
140  row[self._column_index['expression']].setText(expression_text)
141  return row
142 
143  def flags(self, index):
144  flags = super(PublisherTreeModel, self).flags(index)
145  if (
146  index.column() == self._column_index['expression'] and
147  index.model().data(
148  index.model().index(
149  index.row(),
150  self._column_index['type'],
151  index.parent()),
152  Qt.DisplayRole) == 'bool'
153  ):
154  flags |= Qt.ItemIsUserCheckable
155  return flags
156 
157  def data(self, index, role):
158  if (
159  index.column() == self._column_index['expression'] and
160  index.model().data(
161  index.model().index(
162  index.row(),
163  self._column_index['type'],
164  index.parent()),
165  Qt.DisplayRole) == 'bool'
166  ):
167  if role == Qt.CheckStateRole:
168  value = \
169  index.model().data(
170  index.model().index(
171  index.row(), index.column(), index.parent()),
172  Qt.DisplayRole)
173 
174  if value == 'True':
175  return Qt.Checked
176  if value == 'False':
177  return Qt.Unchecked
178  return Qt.PartiallyChecked
179  return super(PublisherTreeModel, self).data(index, role)
180 
181  def setData(self, index, value, role):
182  if (
183  index.column() == index.column() == self._column_index['expression'] and
184  index.model().data(
185  index.model().index(
186  index.row(), self._column_index['type'], index.parent()),
187  Qt.DisplayRole) == 'bool'
188  ):
189  if role == Qt.CheckStateRole:
190  value = str(value == Qt.Checked)
191  return QStandardItemModel.setData(self, index, value, Qt.EditRole)
192  return QStandardItemModel.setData(self, index, value, role)
def add_publisher(self, publisher_info, top_level_row_number=None)
def _get_data_items_for_path(self, slot_name, slot_type_name, slot_path, kwargs)
def _recursive_create_items(self, parent, slot, slot_name, slot_type_name, slot_path, kwargs)
def _recursive_create_items(self, parent, slot, slot_name, slot_type_name, slot_path, expressions={}, kwargs)


rqt_publisher
Author(s): Dirk Thomas, Dorian Scholz
autogenerated on Wed Apr 21 2021 02:46:47