1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 from python_qt_binding.QtCore import Qt
34 from python_qt_binding.QtGui import QIcon, QStandardItem, QStandardItemModel
35 try:
36 from python_qt_binding.QtGui import QMessageBox
37 except:
38 from python_qt_binding.QtWidgets import QMessageBox
39
40 from detailed_msg_box import WarningMessageBox
41 from master_discovery_fkie.master_info import TopicInfo
45 '''
46 The topic item stored in the topic model. This class stores the topic as
47 U{master_discovery_fkie.TopicInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.TopicInfo>}.
48 The name of the topic represented in HTML.
49 '''
50
51 ITEM_TYPE = QStandardItem.UserType + 36
52 NAME_ROLE = Qt.UserRole + 1
53 NODENAMES_ROLE = Qt.UserRole + 2
54 COL_PUB = 1
55 COL_SUB = 2
56 COL_TYPE = 3
57
58 - def __init__(self, name, topic=None, parent=None):
59 '''
60 Initialize the topic item.
61 @param name: the topic name
62 @type name: C{str}
63 @param topic: the topic info
64 @type topic: U{master_discovery_fkie.TopicInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.TopicInfo>}
65 '''
66 QStandardItem.__init__(self, name)
67 self.parent_item = parent
68 self._publish_thread = None
69 self.topic = TopicInfo(name) if topic is None else topic
70 '''@ivar: topic as U{master_discovery_fkie.TopicInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.TopicInfo>}.'''
71
72
73
74
82
84 '''
85 Updates the representation of the column contains the publisher state.
86 '''
87 if self.parent_item is not None:
88 cfg_col = self.parent_item.child(self.row(), TopicItem.COL_PUB)
89 if cfg_col is not None and isinstance(cfg_col, QStandardItem):
90 cfg_col.setText(str(len(self.topic.publisherNodes)))
91 tooltip = ''.join(['<h4>', 'Publisher [', self.topic.name, ']:</h4><dl>'])
92 for p in self.topic.publisherNodes:
93 tooltip = ''.join([tooltip, '<dt>', p, '</dt>'])
94 tooltip = ''.join([tooltip, '</dl>'])
95 if len(self.topic.publisherNodes) > 0:
96 cfg_col.setToolTip(''.join(['<div>', tooltip, '</div>']))
97
99 '''
100 Updates the representation of the column contains the subscriber state.
101 '''
102 if self.parent_item is not None:
103 cfg_col = self.parent_item.child(self.row(), TopicItem.COL_SUB)
104 if cfg_col is not None and isinstance(cfg_col, QStandardItem):
105 cfg_col.setText(str(len(self.topic.subscriberNodes)))
106 tooltip = ''.join(['<h4>', 'Subscriber [', self.topic.name, ']:</h4><dl>'])
107 for p in self.topic.subscriberNodes:
108 tooltip = ''.join([tooltip, '<dt>', p, '</dt>'])
109 tooltip = ''.join([tooltip, '</dl>'])
110 if len(self.topic.subscriberNodes) > 0:
111 cfg_col.setToolTip(''.join(['<div>', tooltip, '</div>']))
112
114 '''
115 Updates the representation of the column contains the type of the topic.
116 '''
117 if self.parent_item is not None:
118 cfg_col = self.parent_item.child(self.row(), TopicItem.COL_TYPE)
119 if cfg_col is not None and isinstance(cfg_col, QStandardItem):
120 cfg_col.setText(self.topic.type if self.topic.type and self.topic.type != 'None' else 'unknown type')
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
150 self.updateIconView(QIcon(':/icons/state_off.png'))
151
153 self.updateIconView(QIcon(':/icons/state_part.png'))
154
156 self.updateIconView(QIcon(':/icons/state_run.png'))
157
159 self._publish_thread = None
160 self.setIcon(QIcon())
161
163 WarningMessageBox(QMessageBox.Warning, "Publish error",
164 'Error while publish to %s' % self.topic.name,
165 tr(msg)).exec_()
166
169
170 - def data(self, role):
171 if role == self.NAME_ROLE:
172 return self.topic.name
173 elif role == self.NODENAMES_ROLE:
174 return str(self.topic.publisherNodes) + str(self.topic.subscriberNodes)
175 else:
176 return QStandardItem.data(self, role)
177
178 @classmethod
180 '''
181 Creates the list of the items from topic. This list is used for the
182 visualization of topic data as a table row.
183 @param topic: the topic name
184 @type topic: C{str}
185 @param root: The parent QStandardItem
186 @type root: U{QStandardItem<https://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItem.html>}
187 @return: the list for the representation as a row
188 @rtype: C{[L{TopicItem} or U{QStandardItem<https://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItem.html>}, ...]}
189 '''
190 items = []
191 item = TopicItem(topic.name, topic, parent=root)
192 items.append(item)
193 pubItem = QStandardItem()
194
195 items.append(pubItem)
196 subItem = QStandardItem()
197
198 items.append(subItem)
199 typeItem = QStandardItem()
200
201 items.append(typeItem)
202 return items
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226 -class TopicModel(QStandardItemModel):
227 '''
228 The model to manage the list with topics in ROS network.
229 '''
230 header = [('Name', 300),
231 ('Publisher', 50),
232 ('Subscriber', 50),
233 ('Type', -1)]
234 '''@ivar: the list with columns C{[(name, width), ...]}'''
235
237 '''
238 Creates a new list model.
239 '''
240 QStandardItemModel.__init__(self)
241 self.setColumnCount(len(TopicModel.header))
242 self.setHorizontalHeaderLabels([label for label, _ in TopicModel.header])
243 self.pyqt_workaround = dict()
244
246 '''
247 @param index: parent of the list
248 @type index: U{QtCore.QModelIndex<https://srinikom.github.io/pyside-docs/PySide/QtCore/QModelIndex.html>}
249 @return: Flag or the requested item
250 @rtype: U{QtCore.Qt.ItemFlag<https://srinikom.github.io/pyside-docs/PySide/QtCore/Qt.html>}
251 @see: U{http://www.pyside.org/docs/pyside-1.0.1/PySide/QtCore/Qt.html}
252 '''
253 if not index.isValid():
254 return Qt.NoItemFlags
255 return Qt.ItemIsEnabled | Qt.ItemIsSelectable
256
257 - def updateModelData(self, topics, added_topics, updated_topics, removed_topics):
258 '''
259 Updates the topics model. New topic will be inserted in sorting order. Not
260 available topics removed from the model.
261 @param topics: The dictionary with topics
262 @type topics: C{dict(topic name : U{master_discovery_fkie.TopicInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.TopicInfo>}, ...)}
263 @param added_topics: the list of new topics in the :topics: list
264 @type added_topics: list or set
265 @param updated_topics: the list of updated topics in the :topics: list
266 @type updated_topics: list or set
267 @param removed_topics: the list of removed topics in the :topics: list
268 @type removed_topics: list or set
269 '''
270 root = self.invisibleRootItem()
271
272 for i in reversed(range(root.rowCount())):
273 topicItem = root.child(i)
274 if topicItem.topic.name in removed_topics:
275 root.removeRow(i)
276 try:
277 del self.pyqt_workaround[topicItem.topic.name]
278 except:
279 pass
280 elif topicItem.topic.name in updated_topics:
281 topicItem.updateView()
282
283
284
285 for topic_name in added_topics:
286 try:
287 doAddItem = True
288 topic = topics[topic_name]
289 for i in range(root.rowCount()):
290 if topic_name not in updated_topics:
291 topicItem = root.child(i)
292 if cmp(topicItem.topic.name, topic_name) > 0:
293 new_item_row = TopicItem.getItemList(topic, root)
294 root.insertRow(i, new_item_row)
295 self.pyqt_workaround[topic_name] = new_item_row[0]
296 new_item_row[0].updateView()
297 doAddItem = False
298 break
299 else:
300 doAddItem = False
301 break
302 if doAddItem:
303 new_item_row = TopicItem.getItemList(topic, root)
304 root.appendRow(new_item_row)
305 self.pyqt_workaround[topic_name] = new_item_row[0]
306 new_item_row[0].updateView()
307 except:
308 pass
309
310
311
312
314 '''
315 Returns for given topics the list of QModelIndex in this model.
316 :param publisher: the list of publisher topics
317 :type publisher: [str, ...]
318 :param subscriber: the list of subscriber topics
319 :type subscriber: [str, ...]
320 :return: the list of QModelIndex
321 :rtype: [QtCore.QModelIndex, ...]
322 '''
323 result = []
324 root = self.invisibleRootItem()
325 for i in range(root.rowCount()):
326 topicItem = root.child(i)
327 if topicItem.topic.name in publisher:
328 result.append(self.index(i, 0))
329 result.append(self.index(i, 1))
330 if topicItem.topic.name in subscriber:
331 result.append(self.index(i, 0))
332 result.append(self.index(i, 2))
333 return result
334