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


rqt_reconfigure
Author(s): Isaac Saito, Ze'ev Klapow
autogenerated on Sat Jul 6 2019 03:49:38