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 import roslib
00035 roslib.load_manifest('rqt_publisher')
00036 
00037 from python_qt_binding.QtCore import Qt, Signal
00038 from python_qt_binding.QtGui import QStandardItem
00039 
00040 from rqt_py_common.message_tree_model import MessageTreeModel
00041 from rqt_py_common.data_items import ReadonlyItem, CheckableItem
00042 
00043 
00044 class PublisherTreeModel(MessageTreeModel):
00045     _column_names = ['topic', 'type', 'rate', 'expression']
00046     item_value_changed = Signal(int, str, str, str, object)
00047 
00048     def __init__(self, parent=None):
00049         super(PublisherTreeModel, self).__init__(parent)
00050         self._column_index = {}
00051         for column_name in self._column_names:
00052             self._column_index[column_name] = len(self._column_index)
00053         self.clear()
00054 
00055         self._item_change_lock = threading.Lock()
00056         self.itemChanged.connect(self.handle_item_changed)
00057 
00058     def clear(self):
00059         super(PublisherTreeModel, self).clear()
00060         self.setHorizontalHeaderLabels(self._column_names)
00061 
00062     def get_publisher_ids(self, index_list):
00063         return [item._user_data['publisher_id'] for item in self._get_toplevel_items(index_list)]
00064 
00065     def remove_items_with_parents(self, index_list):
00066         for item in self._get_toplevel_items(index_list):
00067             self.removeRow(item.row())
00068 
00069     def handle_item_changed(self, item):
00070         if not self._item_change_lock.acquire(False):
00071             #qDebug('PublisherTreeModel.handle_item_changed(): could not acquire lock')
00072             return
00073         # lock has been acquired
00074         topic_name = item._path
00075         column_name = self._column_names[item.column()]
00076         if item.isCheckable():
00077             new_value = str(item.checkState() == Qt.Checked)
00078         else:
00079             new_value = item.text().strip()
00080         #print 'PublisherTreeModel.handle_item_changed(): %s, %s, %s' % (topic_name, column_name, new_value)
00081 
00082         self.item_value_changed.emit(item._user_data['publisher_id'], topic_name, column_name, new_value, item.setText)
00083 
00084         # release lock
00085         self._item_change_lock.release()
00086 
00087     def remove_publisher(self, publisher_id):
00088         for top_level_row_number in range(self.rowCount()):
00089             item = self.item(top_level_row_number)
00090             if item is not None and item._user_data['publisher_id'] == publisher_id:
00091                 self.removeRow(top_level_row_number)
00092                 return top_level_row_number
00093         return None
00094 
00095     def update_publisher(self, publisher_info):
00096         top_level_row_number = self.remove_publisher(publisher_info['publisher_id'])
00097         self.add_publisher(publisher_info, top_level_row_number)
00098 
00099     def add_publisher(self, publisher_info, top_level_row_number=None):
00100         # recursively create widget items for the message's slots
00101         parent = self
00102         slot = publisher_info['message_instance']
00103         slot_name = publisher_info['topic_name']
00104         slot_type_name = publisher_info['message_instance']._type
00105         slot_path = publisher_info['topic_name']
00106         user_data = {'publisher_id': publisher_info['publisher_id']}
00107         kwargs = {
00108             'user_data': user_data,
00109             'top_level_row_number': top_level_row_number,
00110             'expressions': publisher_info['expressions'],
00111         }
00112         top_level_row = self._recursive_create_items(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), ReadonlyItem(slot_type_name), QStandardItem(''), ReadonlyItem(''))
00122         expression_item = QStandardItem('')
00123         expression_item.setToolTip('enter valid Python expression here, using "i" as counter and functions from math, random and time modules')
00124         return (ReadonlyItem(slot_name), QStandardItem(slot_type_name), ReadonlyItem(''), expression_item)
00125 
00126     def _recursive_create_items(self, parent, slot, slot_name, slot_type_name, slot_path, expressions={}, **kwargs):
00127         row, is_leaf_node = super(PublisherTreeModel, self)._recursive_create_items(parent, slot, slot_name, slot_type_name, slot_path, expressions=expressions, **kwargs)
00128         if is_leaf_node:
00129             expression_text = expressions.get(slot_path, repr(slot))
00130             row[self._column_index['expression']].setText(expression_text)
00131         return row


rqt_publisher
Author(s): Dorian Scholz
autogenerated on Fri Jan 3 2014 11:55:21