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


rqt_reconfigure
Author(s): Isaac Saito, Ze'ev Klapow
autogenerated on Sat Jul 15 2017 02:25:06