publisher_tree_model.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 # Copyright (c) 2011, Dorian Scholz, TU Darmstadt
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #   * Redistributions of source code must retain the above copyright
00011 #     notice, this list of conditions and the following disclaimer.
00012 #   * Redistributions in binary form must reproduce the above
00013 #     copyright notice, this list of conditions and the following
00014 #     disclaimer in the documentation and/or other materials provided
00015 #     with the distribution.
00016 #   * Neither the name of the TU Darmstadt nor the names of its
00017 #     contributors may be used to endorse or promote products derived
00018 #     from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
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             #qDebug('PublisherTreeModel.handle_item_changed(): could not acquire lock')
00069             return
00070         # lock has been acquired
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         #print 'PublisherTreeModel.handle_item_changed(): %s, %s, %s' % (topic_name, column_name, new_value)
00078 
00079         self.item_value_changed.emit(item._user_data['publisher_id'], topic_name, column_name, new_value, item.setText)
00080 
00081         # release lock
00082         self._item_change_lock.release()
00083 
00084     def remove_publisher(self, publisher_id):
00085         for top_level_row_number in range(self.rowCount()):
00086             item = self.item(top_level_row_number)
00087             if item is not None and item._user_data['publisher_id'] == publisher_id:
00088                 self.removeRow(top_level_row_number)
00089                 return top_level_row_number
00090         return None
00091 
00092     def update_publisher(self, publisher_info):
00093         top_level_row_number = self.remove_publisher(publisher_info['publisher_id'])
00094         self.add_publisher(publisher_info, top_level_row_number)
00095 
00096     def add_publisher(self, publisher_info, top_level_row_number=None):
00097         # recursively create widget items for the message's slots
00098         parent = self
00099         slot = publisher_info['message_instance']
00100         slot_name = publisher_info['topic_name']
00101         slot_type_name = publisher_info['message_instance']._type
00102         slot_path = publisher_info['topic_name']
00103         user_data = {'publisher_id': publisher_info['publisher_id']}
00104         kwargs = {
00105             'user_data': user_data,
00106             'top_level_row_number': top_level_row_number,
00107             'expressions': publisher_info['expressions'],
00108         }
00109         top_level_row = self._recursive_create_items(parent, slot, slot_name, slot_type_name, slot_path, **kwargs)
00110 
00111         # fill tree widget columns of top level item
00112         if publisher_info['enabled']:
00113             top_level_row[self._column_index['topic']].setCheckState(Qt.Checked)
00114         top_level_row[self._column_index['rate']].setText(str(publisher_info['rate']))
00115 
00116     def _get_data_items_for_path(self, slot_name, slot_type_name, slot_path, **kwargs):
00117         if slot_name.startswith('/'):
00118             return (CheckableItem(slot_name), ReadonlyItem(slot_type_name), QStandardItem(''), ReadonlyItem(''))
00119         expression_item = QStandardItem('')
00120         expression_item.setToolTip('enter valid Python expression here, using "i" as counter and functions from math, random and time modules')
00121         return (ReadonlyItem(slot_name), QStandardItem(slot_type_name), ReadonlyItem(''), expression_item)
00122 
00123     def _recursive_create_items(self, parent, slot, slot_name, slot_type_name, slot_path, expressions={}, **kwargs):
00124         row, is_leaf_node = super(PublisherTreeModel, self)._recursive_create_items(parent, slot, slot_name, slot_type_name, slot_path, expressions=expressions, **kwargs)
00125         if is_leaf_node:
00126             expression_text = expressions.get(slot_path, repr(slot))
00127             row[self._column_index['expression']].setText(expression_text)
00128         return row
00129 
00130     def flags(self, index):
00131         flags = super(PublisherTreeModel, self).flags(index)
00132         if (
00133             index.column() == self._column_index['expression'] and
00134             index.model().data(index.model().index(index.row(), self._column_index['type'], index.parent()), Qt.DisplayRole) == 'bool'
00135         ):
00136             flags |= Qt.ItemIsUserCheckable
00137         return flags
00138 
00139     def data(self, index, role):
00140         if (
00141             index.column() == self._column_index['expression'] and
00142             index.model().data(index.model().index(index.row(), self._column_index['type'], index.parent()), Qt.DisplayRole) == 'bool'
00143         ):
00144             if role == Qt.CheckStateRole:
00145                 value = index.model().data(index.model().index(index.row(), index.column(), index.parent()), Qt.DisplayRole)
00146                 if value == 'True':
00147                     return Qt.Checked
00148                 if value == 'False':
00149                     return Qt.Unchecked
00150                 return Qt.PartiallyChecked
00151         return super(PublisherTreeModel, self).data(index, role)
00152 
00153     def setData(self, index, value, role):
00154         if (
00155             index.column() == index.column() == self._column_index['expression'] and
00156             index.model().data(index.model().index(index.row(), self._column_index['type'], index.parent()), Qt.DisplayRole) == 'bool'
00157         ):
00158             if role == Qt.CheckStateRole:
00159                 value = str(value == Qt.Checked)
00160                 return QStandardItemModel.setData(self, index, value, Qt.EditRole)
00161         return QStandardItemModel.setData(self, index, value, role)


rqt_publisher
Author(s): Dorian Scholz
autogenerated on Mon May 1 2017 02:25:53