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