File indexing completed on 2024-05-19 05:42:14

0001 // ct_lvtmdl_treefiltermodel.cpp                                     -*-C++-*-
0002 
0003 /*
0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk>
0005 // SPDX-License-Identifier: Apache-2.0
0006 //
0007 // Licensed under the Apache License, Version 2.0 (the "License");
0008 // you may not use this file except in compliance with the License.
0009 // You may obtain a copy of the License at
0010 //
0011 //     http://www.apache.org/licenses/LICENSE-2.0
0012 //
0013 // Unless required by applicable law or agreed to in writing, software
0014 // distributed under the License is distributed on an "AS IS" BASIS,
0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016 // See the License for the specific language governing permissions and
0017 // limitations under the License.
0018 */
0019 
0020 #include <ct_lvtmdl_treefiltermodel.h>
0021 
0022 #include <ct_lvtshr_fuzzyutil.h>
0023 
0024 namespace Codethink::lvtmdl {
0025 
0026 // --------------------------------------------
0027 // struct TreeFilterModelPrivate
0028 // --------------------------------------------
0029 struct TreeFilterModel::TreeFilterModelPrivate {
0030     std::string filter;
0031 };
0032 
0033 // --------------------------------------------
0034 // class TreeFilterModel
0035 // --------------------------------------------
0036 TreeFilterModel::TreeFilterModel(): d(std::make_unique<TreeFilterModelPrivate>())
0037 {
0038 }
0039 
0040 TreeFilterModel::~TreeFilterModel() noexcept = default;
0041 
0042 void TreeFilterModel::setFilter(const QString& filter)
0043 {
0044     d->filter = filter.toStdString();
0045     invalidate();
0046 }
0047 
0048 bool TreeFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
0049 {
0050     // Don't try to filter if there's no filter.
0051     if (d->filter.empty()) {
0052         return true; // RETURN
0053     }
0054 
0055     auto data = sourceModel()->index(sourceRow, 0, sourceParent).data(Qt::DisplayRole).toString().toStdString();
0056 
0057     const bool show = data.find(d->filter) != std::string::npos;
0058 
0059     if (show) {
0060         return true; // RETURN
0061     }
0062 
0063     // If we don't have an inner string, use the levensteinDistance.
0064     // we accept an error factor of 2 letters
0065     bool foundFuzzy = lvtshr::FuzzyUtil::levensteinDistance(data, d->filter) < 3;
0066     if (foundFuzzy) {
0067         return true; // RETURN
0068     }
0069 
0070     // If we don't have an exact match, and we don't have a fuzzy match,
0071     // this can be a folder. and an item inside of the folder could be
0072     // visible.
0073     auto currIdx = sourceModel()->index(sourceRow, 0, sourceParent);
0074     if (sourceModel()->rowCount(currIdx) != 0) {
0075         const bool showFolder = data.find(d->filter) != std::string::npos;
0076 
0077         if (showFolder) {
0078             return true; // RETURN
0079         }
0080 
0081         // maybe this is slow, we need to test.
0082         for (int i = 0; i < sourceModel()->rowCount(currIdx); i++) {
0083             if (filterAcceptsRow(i, currIdx)) {
0084                 return true; // RETURN
0085             }
0086         }
0087         return false; // RETURN
0088     }
0089 
0090     return false; // RETURN
0091 }
0092 
0093 } // end namespace Codethink::lvtmdl