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 import threading
00033
00034 from python_qt_binding.QtCore import Qt, Signal
00035 from python_qt_binding.QtGui import QStandardItem, QStandardItemModel
00036
00037 from rqt_py_common.message_tree_model import MessageTreeModel
00038 from rqt_py_common.data_items import ReadonlyItem, CheckableItem
00039
00040
00041 class PublisherTreeModel(MessageTreeModel):
00042 _column_names = ['topic', 'type', 'rate', 'expression']
00043 item_value_changed = Signal(int, str, str, str, object)
00044
00045 def __init__(self, parent=None):
00046 super(PublisherTreeModel, self).__init__(parent)
00047 self._column_index = {}
00048 for column_name in self._column_names:
00049 self._column_index[column_name] = len(self._column_index)
00050 self.clear()
00051
00052 self._item_change_lock = threading.Lock()
00053 self.itemChanged.connect(self.handle_item_changed)
00054
00055 def clear(self):
00056 super(PublisherTreeModel, self).clear()
00057 self.setHorizontalHeaderLabels(self._column_names)
00058
00059 def get_publisher_ids(self, index_list):
00060 return [item._user_data['publisher_id'] for item in self._get_toplevel_items(index_list)]
00061
00062 def remove_items_with_parents(self, index_list):
00063 for item in self._get_toplevel_items(index_list):
00064 self.removeRow(item.row())
00065
00066 def handle_item_changed(self, item):
00067 if not self._item_change_lock.acquire(False):
00068
00069 return
00070
00071 topic_name = item._path
00072 column_name = self._column_names[item.column()]
00073 if item.isCheckable():
00074 new_value = str(item.checkState() == Qt.Checked)
00075 else:
00076 new_value = item.text().strip()
00077
00078
00079
00080 self.item_value_changed.emit(
00081 item._user_data['publisher_id'], topic_name, column_name, new_value, item.setText)
00082
00083
00084 self._item_change_lock.release()
00085
00086 def remove_publisher(self, publisher_id):
00087 for top_level_row_number in range(self.rowCount()):
00088 item = self.item(top_level_row_number)
00089 if item is not None and item._user_data['publisher_id'] == publisher_id:
00090 self.removeRow(top_level_row_number)
00091 return top_level_row_number
00092 return None
00093
00094 def update_publisher(self, publisher_info):
00095 top_level_row_number = self.remove_publisher(publisher_info['publisher_id'])
00096 self.add_publisher(publisher_info, top_level_row_number)
00097
00098 def add_publisher(self, publisher_info, top_level_row_number=None):
00099
00100 parent = self
00101 slot = publisher_info['message_instance']
00102 slot_name = publisher_info['topic_name']
00103 slot_type_name = publisher_info['message_instance']._type
00104 slot_path = publisher_info['topic_name']
00105 user_data = {'publisher_id': publisher_info['publisher_id']}
00106 kwargs = {
00107 'user_data': user_data,
00108 'top_level_row_number': top_level_row_number,
00109 'expressions': publisher_info['expressions'],
00110 }
00111 top_level_row = self._recursive_create_items(
00112 parent, slot, slot_name, slot_type_name, slot_path, **kwargs)
00113
00114
00115 if publisher_info['enabled']:
00116 top_level_row[self._column_index['topic']].setCheckState(Qt.Checked)
00117 top_level_row[self._column_index['rate']].setText(str(publisher_info['rate']))
00118
00119 def _get_data_items_for_path(self, slot_name, slot_type_name, slot_path, **kwargs):
00120 if slot_name.startswith('/'):
00121 return (CheckableItem(slot_name),
00122 ReadonlyItem(slot_type_name),
00123 QStandardItem(''),
00124 ReadonlyItem(''))
00125 expression_item = QStandardItem('')
00126 expression_item.setToolTip(
00127 'enter valid Python expression here, using "i" as counter and functions from math, '
00128 'random and time modules')
00129 return (ReadonlyItem(slot_name),
00130 QStandardItem(slot_type_name),
00131 ReadonlyItem(''),
00132 expression_item)
00133
00134 def _recursive_create_items(
00135 self, parent, slot, slot_name, slot_type_name, slot_path, expressions={}, **kwargs):
00136 row, is_leaf_node = super(PublisherTreeModel, self)._recursive_create_items(
00137 parent, slot, slot_name, slot_type_name, slot_path, expressions=expressions, **kwargs)
00138 if is_leaf_node:
00139 expression_text = expressions.get(slot_path, repr(slot))
00140 row[self._column_index['expression']].setText(expression_text)
00141 return row
00142
00143 def flags(self, index):
00144 flags = super(PublisherTreeModel, self).flags(index)
00145 if (
00146 index.column() == self._column_index['expression'] and
00147 index.model().data(
00148 index.model().index(
00149 index.row(),
00150 self._column_index['type'],
00151 index.parent()),
00152 Qt.DisplayRole) == 'bool'
00153 ):
00154 flags |= Qt.ItemIsUserCheckable
00155 return flags
00156
00157 def data(self, index, role):
00158 if (
00159 index.column() == self._column_index['expression'] and
00160 index.model().data(
00161 index.model().index(
00162 index.row(),
00163 self._column_index['type'],
00164 index.parent()),
00165 Qt.DisplayRole) == 'bool'
00166 ):
00167 if role == Qt.CheckStateRole:
00168 value = \
00169 index.model().data(
00170 index.model().index(
00171 index.row(), index.column(), index.parent()),
00172 Qt.DisplayRole)
00173
00174 if value == 'True':
00175 return Qt.Checked
00176 if value == 'False':
00177 return Qt.Unchecked
00178 return Qt.PartiallyChecked
00179 return super(PublisherTreeModel, self).data(index, role)
00180
00181 def setData(self, index, value, role):
00182 if (
00183 index.column() == index.column() == self._column_index['expression'] and
00184 index.model().data(
00185 index.model().index(
00186 index.row(), self._column_index['type'], index.parent()),
00187 Qt.DisplayRole) == 'bool'
00188 ):
00189 if role == Qt.CheckStateRole:
00190 value = str(value == Qt.Checked)
00191 return QStandardItemModel.setData(self, index, value, Qt.EditRole)
00192 return QStandardItemModel.setData(self, index, value, role)