filter_children_model.py
Go to the documentation of this file.
00001 # Software License Agreement (BSD License)
00002 #
00003 # Copyright (c) 2012, Willow Garage, Inc.
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 Willow Garage, Inc. 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 OWNER 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 #
00033 # Author: Isaac Saito
00034 
00035 from __future__ import division
00036 
00037 from python_qt_binding.QtCore import Qt, Signal
00038 from python_qt_binding.QtGui import QSortFilterProxyModel
00039 import rospy
00040 
00041 from rqt_reconfigure.treenode_qstditem import TreenodeQstdItem
00042 
00043 
00044 class FilterChildrenModel(QSortFilterProxyModel):
00045     """
00046     Extending QSortFilterProxyModel, this provides methods to filter children
00047     tree nodes.
00048 
00049     QSortFilterProxyModel filters top-down direction starting from the
00050     top-level of tree, and once a node doesn't hit the query it gets disabled.
00051     Filtering with this class reflects the result from the bottom node.
00052 
00053     Ex.
00054     #TODO example needed here
00055     """
00056 
00057     # Emitted when parameters filtered. int indicates the order/index of
00058     # params displayed.
00059     sig_filtered = Signal(int)
00060 
00061     def __init__(self, parent):
00062         super(FilterChildrenModel, self).__init__(parent)
00063 
00064         # :Key: Internal ID of QModelIndex of each treenode.
00065         # :Value: TreenodeStatus
00066         # self._treenodes = OrderedDict()
00067 
00068         self._parent = parent
00069         self._toplv_parent_prev = None
00070 
00071     def filterAcceptsRow(self, src_row, src_parent_qmindex):
00072         """
00073         Overridden.
00074 
00075         Terminology:
00076         "Treenode" is deliberately used to avoid confusion with "Node" in ROS.
00077 
00078         :type src_row: int
00079         :type src_parent_qmindex: QModelIndex
00080         """
00081         rospy.logdebug('filerAcceptRow 1')
00082         return self._filter_row_recur(src_row, src_parent_qmindex)
00083 
00084     def _filter_row_recur(self, src_row, src_parent_qmindex):
00085         """
00086         :type src_row: int
00087         :type src_parent_qmindex: QModelIndex
00088         """
00089         _src_model = self.sourceModel()
00090         curr_qmindex = _src_model.index(src_row, 0, src_parent_qmindex)
00091         curr_qitem = _src_model.itemFromIndex(curr_qmindex)
00092 
00093         if isinstance(curr_qitem, TreenodeQstdItem):
00094             # If selectable ROS Node, get GRN name
00095             nodename_fullpath = curr_qitem.get_raw_param_name()
00096             text_filter_target = nodename_fullpath
00097             rospy.logdebug('   Nodename full={} '.format(nodename_fullpath))
00098         else:
00099             # If ReadonlyItem, this means items are the parameters, not a part
00100             # of node name. So, get param name.
00101             text_filter_target = curr_qitem.data(Qt.DisplayRole)
00102 
00103         regex = self.filterRegExp()
00104         pos_hit = regex.indexIn(text_filter_target)
00105         if pos_hit >= 0:  # Query hit.
00106             rospy.logdebug('curr data={} row={} col={}'.format(
00107                                                         curr_qmindex.data(),
00108                                                         curr_qmindex.row(),
00109                                                         curr_qmindex.column()))
00110 
00111             # Set all subsequent treenodes True
00112             rospy.logdebug(' FCModel.filterAcceptsRow src_row={}'.format(
00113                             src_row) +
00114                            ' parent row={} data={}'.format(
00115                               src_parent_qmindex.row(),
00116                               src_parent_qmindex.data()) +
00117                            ' filterRegExp={}'.format(regex))
00118 
00119             # If the index is the terminal treenode, parameters that hit
00120             # the query are displayed at the root tree.
00121             _child_index = curr_qmindex.child(0, 0)
00122             if ((not _child_index.isValid()) and
00123                 (isinstance(curr_qitem, TreenodeQstdItem))):
00124                 self._show_params_view(src_row, curr_qitem)
00125 
00126             # Once we find a treenode that hits the query, no need to further
00127             # traverse since what this method wants to know with the given
00128             # index is whether the given index is supposed to be shown or not.
00129             # Thus, just return True here.
00130             return True
00131 
00132         if not isinstance(curr_qitem, TreenodeQstdItem):
00133             return False  # If parameters, no need for recursive filtering.
00134 
00135         # Evaluate children recursively.
00136         row_child = 0
00137         while True:
00138             child_qmindex = curr_qmindex.child(row_child, 0)
00139             if child_qmindex.isValid():
00140                 flag = self._filter_row_recur(row_child, curr_qmindex)
00141                 if flag:
00142                     return True
00143             else:
00144                 return False
00145             row_child += 1
00146         return False
00147 
00148     def _show_params_view(self, src_row, curr_qitem):
00149         """
00150         :type curr_qitem: QStandardItem
00151         """
00152 
00153         rospy.logdebug('_show_params_view data={}'.format(
00154                                   curr_qitem.data(Qt.DisplayRole)))
00155         curr_qitem.enable_param_items()
00156 
00157     def _get_toplevel_parent_recur(self, qmindex):
00158         p = qmindex.parent()
00159         if p.isValid():
00160             self._get_toplevel_parent(p)
00161         return p
00162 
00163     def filterAcceptsColumn(self, source_column, source_parent):
00164         """
00165         Overridden.
00166 
00167         Doing nothing really since columns are not in use.
00168 
00169         :type source_column: int
00170         :type source_parent: QModelIndex
00171         """
00172         rospy.logdebug('FCModel.filterAcceptsCol source_col={} '.format(
00173             source_column) + 'parent col={} row={} data={}'.format(
00174             source_parent.column(), source_parent.row(), source_parent.data()))
00175         return True
00176 
00177     def set_filter(self, filter_):
00178         self._filter = filter_
00179 
00180         # If filtered text is '' (0-length str), invalidate current
00181         # filtering, in the hope of making filtering process faster.
00182         if filter_.get_text == '':
00183             self.invalidate()
00184             rospy.loginfo('filter invalidated.')
00185 
00186         # By calling setFilterRegExp, filterAccepts* methods get kicked.
00187         self.setFilterRegExp(self._filter.get_regexp())


rqt_reconfigure
Author(s): Isaac Saito, Ze'ev Klapow
autogenerated on Mon Oct 6 2014 07:15:23