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 import QtCore
34 from python_qt_binding import QtGui
35
36 import rospy
37 import roslib
38 import roslib.message
39 import roslib.msgs
40 import genpy
41 from master_discovery_fkie.master_info import TopicInfo
42 from detailed_msg_box import WarningMessageBox
43 from parameter_dialog import ParameterDialog, ServiceDialog
47 '''
48 The topic item stored in the topic model. This class stores the topic as
49 L{master_discovery_fkie.TopicInfo}. The name of the topic represented in HTML.
50 '''
51
52 ITEM_TYPE = QtGui.QStandardItem.UserType + 36
53 NAME_ROLE = QtCore.Qt.UserRole + 1
54 NODENAMES_ROLE = QtCore.Qt.UserRole + 2
55 COL_PUB = 1
56 COL_SUB = 2
57 COL_TYPE = 3
58
59
60 - def __init__(self, name, topic=None, parent=None):
61 '''
62 Initialize the topic item.
63 @param name: the topic name
64 @type name: C{str}
65 '''
66 QtGui.QStandardItem.__init__(self, name)
67 self.parent_item = parent
68 '''@ivar: service info as L{master_discovery_fkie.ServiceInfo}.'''
69 self._publish_thread = None
70 self.topic = TopicInfo(name) if topic is None else topic
71
72
73
74
82
84 '''
85 Updates the representation of the column contains the publisher state.
86 '''
87 if not self.parent_item is None:
88 cfg_col = self.parent_item.child(self.row(), TopicItem.COL_PUB)
89 if not cfg_col is None and isinstance(cfg_col, QtGui.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 not self.parent_item is None:
103 cfg_col = self.parent_item.child(self.row(), TopicItem.COL_SUB)
104 if not cfg_col is None and isinstance(cfg_col, QtGui.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 not self.parent_item is None:
118 cfg_col = self.parent_item.child(self.row(), TopicItem.COL_TYPE)
119 if not cfg_col is None and isinstance(cfg_col, QtGui.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(QtGui.QIcon(':/icons/state_off.png'))
151
153 self.updateIconView(QtGui.QIcon(':/icons/state_part.png'))
154
156 self.updateIconView(QtGui.QIcon(':/icons/state_run.png'))
157
159 self._publish_thread = None
160 self.setIcon(QtGui.QIcon())
161
163 WarningMessageBox(QtGui.QMessageBox.Warning, "Publish error",
164 'Error while publish to %s'%self.topic.name,
165 str(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 QtGui.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 name: the topic name
184 @type name: C{str}
185 @param root: The parent QStandardItem
186 @type root: L{PySide.QtGui.QStandardItem}
187 @return: the list for the representation as a row
188 @rtype: C{[L{TopicItem} or L{PySide.QtGui.QStandardItem}, ...]}
189 '''
190 items = []
191 item = TopicItem(topic.name, topic, parent=root)
192 items.append(item)
193 pubItem = QtGui.QStandardItem()
194
195 items.append(pubItem)
196 subItem = QtGui.QStandardItem()
197
198 items.append(subItem)
199 typeItem = QtGui.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(QtGui.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 QtGui.QStandardItemModel.__init__(self)
241 self.setColumnCount(len(TopicModel.header))
242 self.setHorizontalHeaderLabels([label for label, width in TopicModel.header])
243 self.pyqt_workaround = dict()
244
246 '''
247 @param index: parent of the list
248 @type index: L{PySide.QtCore.QModelIndex}
249 @return: Flag or the requested item
250 @rtype: L{PySide.QtCore.Qt.ItemFlag}
251 @see: U{http://www.pyside.org/docs/pyside-1.0.1/PySide/QtCore/Qt.html}
252 '''
253 if not index.isValid():
254 return QtCore.Qt.NoItemFlags
255 return QtCore.Qt.ItemIsEnabled | QtCore.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 : L{master_discovery_fkie.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 updated = []
272
273 for i in reversed(range(root.rowCount())):
274 topicItem = root.child(i)
275 if topicItem.topic.name in removed_topics:
276 root.removeRow(i)
277 try:
278 del self.pyqt_workaround[topicItem.topic.name]
279 except:
280 pass
281 elif topicItem.topic.name in updated_topics:
282 topicItem.updateView()
283
284
285
286 for topic_name in added_topics:
287 try:
288 doAddItem = True
289 topic = topics[topic_name]
290 for i in range(root.rowCount()):
291 if not topic_name in updated_topics:
292 topicItem = root.child(i)
293 if cmp(topicItem.topic.name, topic_name) > 0:
294 new_item_row = TopicItem.getItemList(topic, root)
295 root.insertRow(i, new_item_row)
296 self.pyqt_workaround[topic_name] = new_item_row[0]
297 new_item_row[0].updateView()
298 doAddItem = False
299 break
300 else:
301 doAddItem = False
302 break
303 if doAddItem:
304 new_item_row = TopicItem.getItemList(topic, root)
305 root.appendRow(new_item_row)
306 self.pyqt_workaround[topic_name] = new_item_row[0]
307 new_item_row[0].updateView()
308 except:
309 pass
310
311
312
313
315 '''
316 Returns for given topics the list of QModelIndex in this model.
317 :param publisher: the list of publisher topics
318 :type publisher: [str, ...]
319 :param subscriber: the list of subscriber topics
320 :type subscriber: [str, ...]
321 :return: the list of QModelIndex
322 :rtype: [QtCore.QModelIndex, ...]
323 '''
324 result = []
325 root = self.invisibleRootItem()
326 for i in range(root.rowCount()):
327 topicItem = root.child(i)
328 if topicItem.topic.name in publisher:
329 result.append(self.index(i, 0))
330 result.append(self.index(i, 1))
331 if topicItem.topic.name in subscriber:
332 result.append(self.index(i, 0))
333 result.append(self.index(i, 2))
334 return result
335