Package node_manager_fkie :: Module service_list_model
[frames] | no frames]

Source Code for Module node_manager_fkie.service_list_model

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2012, Fraunhofer FKIE/US, Alexander Tiderko 
  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 Fraunhofer 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 OWNER 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   
 33  import re 
 34  import rospy 
 35  from python_qt_binding.QtCore import Qt 
 36  from python_qt_binding.QtGui import QStandardItem, QStandardItemModel 
 37   
 38  from master_discovery_fkie.common import get_hostname 
 39  from node_manager_fkie.common import lnamespace, namespace, normns, utf8 
 40  import node_manager_fkie as nm 
41 42 43 -class ServiceItem(QStandardItem):
44 ''' 45 The service item stored in the service model. This class stores the service as 46 U{master_discovery_fkie.ServiceInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.ServiceInfo>}. 47 The name of the service is represented in HTML. 48 ''' 49 50 ITEM_TYPE = QStandardItem.UserType + 37 51 NAME_ROLE = Qt.UserRole + 1 52 TYPE_ROLE = Qt.UserRole + 2 53 NODENAMES_ROLE = Qt.UserRole + 3 54
55 - def __init__(self, service, parent=None):
56 ''' 57 Initialize the service item. 58 @param service: the service object to view 59 @type service: U{master_discovery_fkie.ServiceInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.ServiceInfo>} 60 ''' 61 QStandardItem.__init__(self, service.name) 62 self._parent_item = parent 63 self.service = service 64 '''@ivar: service info as U{master_discovery_fkie.ServiceInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.ServiceInfo>}.''' 65 self._with_namespace = rospy.names.SEP in service.name
66 67 @property
68 - def name(self):
69 return self.text()
70 71 @name.setter
72 - def name(self, new_name):
73 self.setText(new_name)
74 75 @property
76 - def service_type_str(self):
77 stype = '' 78 try: 79 stype = utf8(self.service.get_service_class(False)) 80 except Exception: 81 pass 82 return stype
83 84 @property
85 - def parent_item(self):
86 return self._parent_item
87 88 @parent_item.setter
89 - def parent_item(self, parent_item):
90 self._parent_item = parent_item 91 if parent_item is None: 92 self.setText(self.text()) 93 self._with_namespace = rospy.names.SEP in self.text() 94 else: 95 new_name = self.text().replace(parent_item.get_namespace(), '', 1) 96 self.setText(new_name) 97 self._with_namespace = rospy.names.SEP in new_name
98 99 @property
100 - def with_namespace(self):
101 ''' 102 Returns `True` if the topic name contains a '/' in his name 103 104 :rtype: bool 105 ''' 106 return self._with_namespace
107
108 - def update_view(self, service_info=None):
109 ''' 110 Updates the view 111 ''' 112 if service_info is not None: 113 self.service = service_info 114 self.updateServiceView()
115
116 - def updateServiceView(self):
117 ''' 118 Updates the view of the service on changes. 119 120 :param parent: the item containing this item 121 :type parent: U{QtGui.QStandardItem<https://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItem.html>} 122 ''' 123 if self.parent_item is not None: 124 # update type view 125 child = self.parent_item.child(self.row(), 1) 126 if child is not None: 127 self.updateTypeView(self.service, child)
128
129 - def type(self):
131 132 @classmethod
133 - def create_item_list(self, service, root):
134 ''' 135 Creates the list of the items from service. This list is used for the 136 visualization of service data as a table row. 137 138 :param service: the service data 139 :type service: U{master_discovery_fkie.ServiceInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.ServiceInfo>} 140 :return: the list for the representation as a row 141 :rtype: C{[L{ServiceItem} or U{QtGui.QStandardItem<https://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItem.html>}, ...]} 142 ''' 143 items = [] 144 item = ServiceItem(service, parent=root) 145 # removed tooltip for clarity !!! 146 # item.setToolTip(''.join(['<div><h4>', utf8(service.name), '</h4><dl><dt>', utf8(service.uri),'</dt></dl></div>'])) 147 items.append(item) 148 typeItem = QStandardItem() 149 ServiceItem.updateTypeView(service, typeItem) 150 items.append(typeItem) 151 return items
152 153 @classmethod
154 - def updateTypeView(cls, service, item):
155 ''' 156 Updates the representation of the column contains the type of the service. 157 @param service: the service data 158 @type service: U{master_discovery_fkie.ServiceInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.ServiceInfo>} 159 @param item: corresponding item in the model 160 @type item: L{ServiceItem} 161 ''' 162 try: 163 if service.isLocal and service.type: 164 service_class = service.get_service_class(nm.is_local(get_hostname(service.uri))) 165 item.setText(service_class._type) 166 elif service.type: 167 item.setText(service.type) 168 else: 169 item.setText('unknown type') 170 # removed tooltip for clarity !!! 171 # tooltip = '' 172 # tooltip = ''.join([tooltip, '<h4>', service_class._type, '</h4>']) 173 # tooltip = ''.join([tooltip, '<b><u>', 'Request', ':</u></b>']) 174 # tooltip = ''.join([tooltip, '<dl><dt>', utf8(service_class._request_class.__slots__), '</dt></dl>']) 175 # 176 # tooltip = ''.join([tooltip, '<b><u>', 'Response', ':</u></b>']) 177 # tooltip = ''.join([tooltip, '<dl><dt>', utf8(service_class._response_class.__slots__), '</dt></dl>']) 178 # 179 # item.setToolTip(''.join(['<div>', tooltip, '</div>'])) 180 item.setToolTip('') 181 except Exception: 182 if not service.isLocal: 183 tooltip = ''.join(['<h4>', 'Service type is not available due to he running on another host.', '</h4>']) 184 item.setToolTip(''.join(['<div>', tooltip, '</div>']))
185
186 - def data(self, role):
187 if role == self.NAME_ROLE: 188 return self.service.name 189 elif role == self.TYPE_ROLE: 190 return self.service_type_str 191 elif role == self.NODENAMES_ROLE: 192 return utf8(self.service.serviceProvider) 193 else: 194 return QStandardItem.data(self, role)
195
196 - def __eq__(self, item):
197 ''' 198 Compares the name of service. 199 ''' 200 if isinstance(item, str) or isinstance(item, unicode): 201 return self.service.name.lower() == item.lower() 202 elif not (item is None): 203 return self.service.name.lower() == item.service.name.lower() 204 return False
205 #
206 # def __gt__(self, item): 207 # ''' 208 # Compares the name of service. 209 # ''' 210 # if isinstance(item, str) or isinstance(item, unicode): 211 # return self.service.name.lower() > item.lower() 212 # elif not (item is None): 213 # return self.service.name.lower() > item.service.name.lower() 214 # return False 215 216 217 # ############################################################################### 218 # ############# GrouptItem ############## 219 # ############################################################################### 220 -class ServiceGroupItem(QStandardItem):
221 ''' 222 The ServiceGroupItem stores the information about a group of nodes. 223 ''' 224 ITEM_TYPE = Qt.UserRole + 45 225
226 - def __init__(self, name, parent=None, is_group=False):
227 ''' 228 Initialize the ServiceGroupItem object with given values. 229 230 :param str name: the name of the group 231 :param parent: the parent item. In most cases this is the HostItem. The variable is used to determine the different columns of the NodeItem. 232 :type parent: :class:`QtGui.QStandardItem` <https://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItem.html> 233 :param bool is_group: True if this is a capability group. In other case it is a namespace group. 234 ''' 235 dname = name 236 if is_group: 237 dname = '{%s}' % name 238 elif name != rospy.names.SEP: 239 dname = '%s/' % name 240 else: 241 dname = 'services@master/' 242 QStandardItem.__init__(self, dname) 243 self.parent_item = parent 244 self._name = name 245 self._is_group = is_group 246 self.is_system_group = name == 'SYSTEM'
247 248 @property
249 - def name(self):
250 ''' 251 The name of this group. 252 253 :rtype: str 254 ''' 255 return self._name
256 257 @name.setter
258 - def name(self, new_name):
259 ''' 260 Set the new name of this group and updates the displayed name of the item. 261 262 :param str new_name: The new name of the group. Used also to identify the group. 263 ''' 264 self._name = new_name 265 if self._is_group: 266 self.setText('{' + self._name + '}') 267 else: 268 self.setText(self._name + '/')
269 270 @property
271 - def is_group(self):
272 return self._is_group
273
274 - def get_namespace(self):
275 name = self._name 276 if type(self) == ServiceGroupItem and self._is_group: 277 name = namespace(self._name) 278 result = name 279 if self.parent_item is not None and type(self.parent_item) != QStandardItem: 280 result = normns(self.parent_item.get_namespace() + rospy.names.SEP) + normns(result + rospy.names.SEP) 281 return normns(result)
282
283 - def count_topics(self):
284 ''' 285 :retrun: Returns count of nodes inside this group. 286 :rtype: int 287 ''' 288 result = 0 289 for i in range(self.rowCount()): 290 item = self.child(i) 291 if isinstance(item, ServiceGroupItem): 292 result += item.count_nodes() 293 elif isinstance(item, ServiceItem): 294 result += 1 295 return result
296
297 - def get_service_items_by_name(self, name, recursive=True):
298 ''' 299 Since the same node can be included by different groups, this method searches 300 for all nodes with given name and returns these items. 301 302 :param str name: The name of the topic 303 :param bool recursive: Searches in (sub) groups 304 :return: The list with node items. 305 :rtype: list(:class:`QtGui.QStandardItem` <https://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItem.html>) 306 ''' 307 result = [] 308 for i in range(self.rowCount()): 309 item = self.child(i) 310 if isinstance(item, ServiceGroupItem): 311 if recursive: 312 result[len(result):] = item.get_service_items_by_name(name) 313 elif isinstance(item, ServiceItem) and item == name: 314 return [item] 315 return result
316
317 - def get_service_items(self, recursive=True):
318 ''' 319 Returns all nodes in this group and subgroups. 320 321 :param bool recursive: returns the nodes of the subgroups 322 :return: The list with node items. 323 :rtype: list(:class:`QtGui.QStandardItem` <https://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItem.html>) 324 ''' 325 result = [] 326 for i in range(self.rowCount()): 327 item = self.child(i) 328 if isinstance(item, ServiceGroupItem): 329 if recursive: 330 result[len(result):] = item.get_service_items() 331 elif isinstance(item, ServiceItem): 332 result.append(item) 333 return result
334 335 @classmethod
336 - def create_item_list(self, name, parent, is_group):
337 ''' 338 Creates the list of the items for this group. This list is used for the 339 visualization of group data as a table row. 340 341 :param str name: the group name 342 :return: the list for the representation as a row 343 :rtype: C{[L{ServiceGroupItem} or U{QStandardItem<https://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItem.html>}, ...]} 344 ''' 345 items = [] 346 item = ServiceGroupItem(name, parent, is_group) 347 items.append(item) 348 typeItem = QStandardItem() 349 items.append(typeItem) 350 return items
351
352 - def get_group_item(self, group_name, is_group=True, nocreate=False):
353 ''' 354 Returns a ServiceGroupItem with given name. If no group with this name exists, a 355 new one will be created. The given name will be split by slashes if exists 356 and subgroups are created. 357 358 :param str group_name: the name of the group 359 :param bool is_group: True if it is a capability group. False if a namespace group. (Default: True) 360 :param bool nocreate: avoid creation of new group if not exists. (Default: False) 361 :return: The group with given name of None if `nocreate` is True and group not exists. 362 :rtype: :class:`ServiceGroupItem` 363 ''' 364 lns, rns = group_name, '' 365 if nm.settings().group_nodes_by_namespace: 366 lns, rns = lnamespace(group_name) 367 if lns == rospy.names.SEP: 368 lns, rns = lnamespace(rns) 369 if lns == rospy.names.SEP: 370 return self 371 for i in range(self.rowCount()): 372 item = self.child(i) 373 if isinstance(item, ServiceGroupItem): 374 if item == lns: 375 if rns: 376 return item.get_group_item(rns, is_group) 377 return item 378 elif item > lns and not nocreate: 379 items = ServiceGroupItem.create_item_list(lns, self, is_group=(is_group and not rns)) 380 self.insertRow(i, items) 381 if rns: 382 return items[0].get_group_item(rns, is_group) 383 return items[0] 384 if nocreate: 385 return None 386 items = ServiceGroupItem.create_item_list(lns, self, is_group=(is_group and not rns)) 387 self.appendRow(items) 388 if rns: 389 return items[0].get_group_item(rns, is_group) 390 return items[0]
391
392 - def add_node(self, service):
393 ''' 394 Adds a new topic with given name. 395 396 :param service: the TopicInfo of the node to create 397 :type service: :class:`TopicInfo` 398 ''' 399 group_item = self 400 if nm.settings().group_nodes_by_namespace: 401 ns = namespace(service.name) 402 if ns != rospy.names.SEP: 403 # insert in the group 404 group_item = self.get_group_item(ns, False) 405 # append new topic row 406 new_item_row = ServiceItem.create_item_list(service, self) 407 group_item._add_row(new_item_row)
408
409 - def _add_row(self, row):
410 self.appendRow(row) 411 row[0].parent_item = self 412 row[0].update_view()
413
414 - def clearup(self, fixed_node_names=None):
415 ''' 416 Removes not running and not configured nodes. 417 418 :param list(str) fixed_node_names: If the list is not None, the node not in the list are set to not running! 419 ''' 420 self._clearup(fixed_node_names) 421 self._clearup_reinsert() 422 self._clearup_riseup()
423
424 - def _clearup(self, fixed_node_names=None):
425 ''' 426 Removes not running and not configured nodes. 427 428 :param list(str) fixed_node_names: If the list is not None, the node not in the list are set to not running! 429 ''' 430 removed = False 431 # move running nodes without configuration to the upper layer, remove not running and duplicate nodes 432 for i in reversed(range(self.rowCount())): 433 item = self.child(i) 434 if isinstance(item, ServiceItem): 435 pass 436 else: # if type(item) == ServiceGroupItem: 437 removed = item._clearup(fixed_node_names) or removed 438 if self.rowCount() == 0 and self.parent_item is not None: 439 self.parent_item._remove_group(self.name) 440 return removed
441
442 - def _clearup_reinsert(self):
443 inserted = False 444 for i in reversed(range(self.rowCount())): 445 item = self.child(i) 446 if isinstance(item, ServiceItem): 447 if item.with_namespace: 448 group_item = self.get_group_item(namespace(item.name), False, nocreate=True) 449 if group_item is not None and group_item != self: 450 inserted = True 451 row = self.takeRow(i) 452 group_item._add_row(row) 453 else: 454 inserted = item._clearup_reinsert() or inserted 455 return inserted
456
457 - def _clearup_riseup(self):
458 changed = False 459 for i in reversed(range(self.rowCount())): 460 item = self.child(i) 461 if isinstance(item, ServiceItem): 462 # remove group if only one node is inside 463 if self.rowCount() == 1: 464 if not self.is_group and not type(self) == QStandardItem: 465 changed = True 466 row = self.takeRow(i) 467 if self.parent_item is not None: 468 self.parent_item._add_row(row) 469 self.parent_item._remove_group(self.name) 470 self.parent_item._clearup_riseup() 471 else: 472 changed = item._clearup_riseup() or changed 473 return changed
474
475 - def _remove_group(self, name):
476 for i in reversed(range(self.rowCount())): 477 item = self.child(i) 478 if type(item) == ServiceGroupItem and item == name and item.rowCount() == 0: 479 self.removeRow(i)
480
481 - def remove_node(self, name):
482 removed = False 483 for i in range(self.rowCount()): 484 item = self.child(i) 485 if type(item) == ServiceItem and item == name: 486 self.removeRow(i) 487 removed = True 488 break 489 elif type(item) == ServiceGroupItem: 490 removed = item.remove_node(name) 491 if removed: 492 break 493 if removed and self.rowCount() == 0: 494 if type(self.parent_item) == ServiceGroupItem: 495 self.parent_item._remove_group(self.name) 496 return removed
497
498 - def update_view(self, updated_srvs, services):
499 for i in range(self.rowCount()): 500 item = self.child(i) 501 if type(item) == ServiceItem: 502 if item.service.name in updated_srvs: 503 item.update_view(services[item.service.name]) 504 elif type(item) == ServiceGroupItem: 505 item.update_view(updated_srvs, services)
506
507 - def index_from_names(self, services):
508 ''' 509 Returns for given topics the list of QModelIndex in this model. 510 511 :param [str] services: the list of service names 512 :return: the list of QModelIndex 513 :rtype: [QtCore.QModelIndex] 514 ''' 515 result = [] 516 for i in range(self.rowCount()): 517 item = self.child(i) 518 if type(item) == ServiceGroupItem: 519 result[len(result):] = item.index_from_names(services) 520 elif type(item) == ServiceItem: 521 if item.service.name in services: 522 result.append(item.index()) 523 return result
524
525 - def type(self):
527
528 - def __eq__(self, item):
529 ''' 530 Compares the name of the group. 531 ''' 532 if isinstance(item, str) or isinstance(item, unicode): 533 return self.name.lower() == item.lower() 534 elif not (item is None): 535 return self.name.lower() == item.name.lower() 536 return False
537
538 - def __ne__(self, item):
539 return not (self == item)
540
541 - def __gt__(self, item):
542 ''' 543 Compares the name of the group. 544 ''' 545 if isinstance(item, str) or isinstance(item, unicode): 546 # put the group with SYSTEM nodes at the end 547 if self.is_system_group: 548 if self.name.lower() != item.lower(): 549 return True 550 elif item.lower() == 'system': 551 return False 552 return self.name.lower() > item.lower() 553 elif not (item is None): 554 # put the group with SYSTEM nodes at the end 555 if item.is_system_group: 556 if self.name.lower() != item.lower(): 557 return True 558 elif self.is_syste_group: 559 return False 560 return self.name.lower() > item.name.lower() 561 return False
562
563 564 -class ServiceModel(QStandardItemModel):
565 ''' 566 The model to manage the list with services in ROS network. 567 ''' 568 header = [('Name', 300), 569 ('Type', -1)] 570 '''@ivar: the list with columns C{[(name, width), ...]}''' 571
572 - def __init__(self):
573 ''' 574 Creates a new list model. 575 ''' 576 QStandardItemModel.__init__(self) 577 self.setColumnCount(len(ServiceModel.header)) 578 self.setHorizontalHeaderLabels([label for label, _ in ServiceModel.header]) 579 self.pyqt_workaround = dict() # workaround for using with PyQt: store the python object to keep the defined attributes in the ServiceItem subclass 580 topics = ['*/get_loggers', '*/set_logger_level'] 581 def_list = ['\A' + n.strip().replace('*', '.*') + '\Z' for n in topics] 582 self._re_cap_systopics = re.compile('|'.join(def_list), re.I) 583 root_items = ServiceGroupItem.create_item_list(rospy.names.SEP, self.invisibleRootItem(), False) 584 self.invisibleRootItem().appendRow(root_items) 585 self._pyqt_workaround_add(rospy.names.SEP, root_items[0])
586
587 - def flags(self, index):
588 ''' 589 :param index: parent of the list 590 :type index: QtCore.QModelIndex<https://srinikom.github.io/pyside-docs/PySide/QtCore/QModelIndex.html> 591 :return: Flag or the requestet item 592 :rtype: QtCore.Qt.ItemFlag<https://srinikom.github.io/pyside-docs/PySide/QtCore/Qt.html> 593 :see: http://www.pyside.org/docs/pyside-1.0.1/PySide/QtCore/Qt.html 594 ''' 595 if not index.isValid(): 596 return Qt.NoItemFlags 597 return Qt.ItemIsEnabled | Qt.ItemIsSelectable
598
599 - def get_cap_group(self, topic_name):
600 match = False 601 try: 602 match = self._re_cap_systopics.match(topic_name) 603 except Exception: 604 pass 605 if match: 606 root = self.get_root_group() 607 for i in range(root.rowCount()): 608 item = root.child(i) 609 if type(item) == ServiceGroupItem: 610 if item == 'SYSTEM' and item.is_group: 611 return item 612 items = ServiceGroupItem.create_item_list('SYSTEM', root, True) 613 root.appendRow(items) 614 self.pyqt_workaround['{SYSTEM}'] = items[0] 615 return items[0] 616 return None
617
618 - def get_root_group(self):
619 root = self.invisibleRootItem() 620 for i in range(root.rowCount()): 621 item = root.child(i) 622 if type(item) == ServiceGroupItem: 623 if item == rospy.names.SEP: 624 return item 625 return None
626
627 - def updateModelData(self, services, added_srvs, updated_srvs, removed_srvs):
628 ''' 629 Updates the service list model. New services will be inserted in sorting 630 order. Not available services removed from the model. 631 632 :param services: The dictionary with services 633 :type services: dict(service name : U{master_discovery_fkie.ServiceInfo<http://docs.ros.org/kinetic/api/master_discovery_fkie/html/modules.html#master_discovery_fkie.master_info.ServiceInfo>}) 634 :param added_srvs: the list of new services in the :service: list 635 :type added_srvs: list or set 636 :param updated_srvs: the list of updated services in the :service: list 637 :type updated_srvs: list or set 638 :param removed_srvs: the list of removed services in the :service: list 639 :type removed_srvs: list or set 640 ''' 641 # first: remove services 642 parents = set() 643 for rm_topic in removed_srvs: 644 new_parent = self._remove_node(rm_topic) 645 if type(new_parent) == ServiceGroupItem: 646 parents.add(new_parent) 647 for parent in parents: 648 parent.clearup() 649 # second: update the existing items 650 root = self.invisibleRootItem() 651 for i in reversed(range(root.rowCount())): 652 item = root.child(i) 653 if type(item) == ServiceGroupItem: 654 item.update_view(updated_srvs, services) 655 # last: add new services 656 for name in added_srvs: 657 try: 658 topic = services[name] 659 # first: add to system group 660 sys_group = self.get_cap_group(name) 661 if sys_group is not None: 662 sys_group.add_node(topic) 663 else: 664 # second add to the root group 665 root_group = self.get_root_group() 666 if root_group is not None: 667 root_group.add_node(topic) 668 except Exception: 669 import traceback 670 print traceback.format_exc() 671 pass
672
673 - def index_from_names(self, services):
674 ''' 675 Returns for given services the list of QModelIndex in this model. 676 677 :param [str] services: the list of service names 678 :return: the list of QModelIndex 679 :rtype: [QtCore.QModelIndex<https://srinikom.github.io/pyside-docs/PySide/QtCore/QModelIndex.html>}] 680 ''' 681 result = [] 682 root = self.invisibleRootItem() 683 for i in range(root.rowCount()): 684 item = root.child(i) 685 if type(item) == ServiceGroupItem: 686 result[len(result):] = item.index_from_names(services) 687 elif type(item) == ServiceItem: 688 if item.service.name in services: 689 result.append(item.index()) 690 return result
691
692 - def _remove_node(self, name):
693 root = self.invisibleRootItem() 694 for i in range(root.rowCount()): 695 item = root.child(i) 696 if type(item) == ServiceGroupItem: 697 parent = item.remove_node(name) 698 if parent is not None: 699 return parent 700 return None
701
702 - def _pyqt_workaround_add(self, name, item):
703 self.pyqt_workaround[name] = item # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass
704
705 - def _pyqt_workaround_rem(self, name):
706 try: 707 del self.pyqt_workaround[name] # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass 708 except Exception: 709 pass
710