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' %
00078         # (topic_name, column_name, new_value)
00079 
00080         self.item_value_changed.emit(
00081             item._user_data['publisher_id'], topic_name, column_name, new_value, item.setText)
00082 
00083         # release lock
00084         self._item_change_lock.release()
00085 
00086     def remove_publisher(self, publisher_id):
00087         for top_level_row_number in range(self.rowCount()):
00088             item = self.item(top_level_row_number)
00089             if item is not None and item._user_data['publisher_id'] == publisher_id:
00090                 self.removeRow(top_level_row_number)
00091                 return top_level_row_number
00092         return None
00093 
00094     def update_publisher(self, publisher_info):
00095         top_level_row_number = self.remove_publisher(publisher_info['publisher_id'])
00096         self.add_publisher(publisher_info, top_level_row_number)
00097 
00098     def add_publisher(self, publisher_info, top_level_row_number=None):
00099         # recursively create widget items for the message's slots
00100         parent = self
00101         slot = publisher_info['message_instance']
00102         slot_name = publisher_info['topic_name']
00103         slot_type_name = publisher_info['message_instance']._type
00104         slot_path = publisher_info['topic_name']
00105         user_data = {'publisher_id': publisher_info['publisher_id']}
00106         kwargs = {
00107             'user_data': user_data,
00108             'top_level_row_number': top_level_row_number,
00109             'expressions': publisher_info['expressions'],
00110         }
00111         top_level_row = self._recursive_create_items(
00112             parent, slot, slot_name, slot_type_name, slot_path, **kwargs)
00113 
00114         # fill tree widget columns of top level item
00115         if publisher_info['enabled']:
00116             top_level_row[self._column_index['topic']].setCheckState(Qt.Checked)
00117         top_level_row[self._column_index['rate']].setText(str(publisher_info['rate']))
00118 
00119     def _get_data_items_for_path(self, slot_name, slot_type_name, slot_path, **kwargs):
00120         if slot_name.startswith('/'):
00121             return (CheckableItem(slot_name),
00122                     ReadonlyItem(slot_type_name),
00123                     QStandardItem(''),
00124                     ReadonlyItem(''))
00125         expression_item = QStandardItem('')
00126         expression_item.setToolTip(
00127             'enter valid Python expression here, using "i" as counter and functions from math, '
00128             'random and time modules')
00129         return (ReadonlyItem(slot_name),
00130                 QStandardItem(slot_type_name),
00131                 ReadonlyItem(''),
00132                 expression_item)
00133 
00134     def _recursive_create_items(
00135             self, parent, slot, slot_name, slot_type_name, slot_path, expressions={}, **kwargs):
00136         row, is_leaf_node = super(PublisherTreeModel, self)._recursive_create_items(
00137             parent, slot, slot_name, slot_type_name, slot_path, expressions=expressions, **kwargs)
00138         if is_leaf_node:
00139             expression_text = expressions.get(slot_path, repr(slot))
00140             row[self._column_index['expression']].setText(expression_text)
00141         return row
00142 
00143     def flags(self, index):
00144         flags = super(PublisherTreeModel, self).flags(index)
00145         if (
00146             index.column() == self._column_index['expression'] and
00147             index.model().data(
00148                 index.model().index(
00149                     index.row(),
00150                     self._column_index['type'],
00151                     index.parent()),
00152                 Qt.DisplayRole) == 'bool'
00153         ):
00154             flags |= Qt.ItemIsUserCheckable
00155         return flags
00156 
00157     def data(self, index, role):
00158         if (
00159             index.column() == self._column_index['expression'] and
00160             index.model().data(
00161                 index.model().index(
00162                     index.row(),
00163                     self._column_index['type'],
00164                     index.parent()),
00165                 Qt.DisplayRole) == 'bool'
00166         ):
00167             if role == Qt.CheckStateRole:
00168                 value = \
00169                     index.model().data(
00170                         index.model().index(
00171                             index.row(), index.column(), index.parent()),
00172                         Qt.DisplayRole)
00173 
00174                 if value == 'True':
00175                     return Qt.Checked
00176                 if value == 'False':
00177                     return Qt.Unchecked
00178                 return Qt.PartiallyChecked
00179         return super(PublisherTreeModel, self).data(index, role)
00180 
00181     def setData(self, index, value, role):
00182         if (
00183             index.column() == index.column() == self._column_index['expression'] and
00184             index.model().data(
00185                 index.model().index(
00186                     index.row(), self._column_index['type'], index.parent()),
00187                 Qt.DisplayRole) == 'bool'
00188         ):
00189             if role == Qt.CheckStateRole:
00190                 value = str(value == Qt.Checked)
00191                 return QStandardItemModel.setData(self, index, value, Qt.EditRole)
00192         return QStandardItemModel.setData(self, index, value, role)


rqt_publisher
Author(s): Dorian Scholz
autogenerated on Thu Jun 6 2019 17:40:36