1+ #include " filtered_tocmodel.hpp"
2+ #include < algorithm>
3+ #include < rapidfuzz/fuzz.hpp>
4+
5+ namespace Okular
6+ {
7+
8+ FilteredTOCModel::FilteredTOCModel (QObject* parent) :
9+ QSortFilterProxyModel { parent }
10+ {
11+ }
12+
13+ bool FilteredTOCModel::filterAcceptsRow (int row,
14+ const QModelIndex& parent) const
15+ {
16+ auto index = sourceModel ()->index (row, 0 , parent);
17+ auto name = sourceModel ()->data (index, Qt::ToolTipRole);
18+
19+ auto x = sourceModel ()->index (row, 0 , parent);
20+ TOCItem* item = static_cast <TOCItem*>(x.internalPointer ());
21+ if (item != nullptr && hasChildrenMatchingTheFilter (item))
22+ return true ;
23+
24+ auto similarity = fuzzCompareWithFilterString (name.toString ());
25+ double minSimilarity = 70 ;
26+
27+ return similarity >= minSimilarity;
28+ }
29+
30+ void FilteredTOCModel::setFilterString (QString filterString)
31+ {
32+ m_filterString = filterString;
33+ invalidateFilter ();
34+ }
35+
36+ QString FilteredTOCModel::getFilterString ()
37+ {
38+ return m_filterString;
39+ }
40+
41+ bool FilteredTOCModel::hasChildrenMatchingTheFilter (const TOCItem* item) const
42+ {
43+ if (itemPassesFilter (item))
44+ return true ;
45+
46+ return std::any_of (item->children .begin (), item->children .end (),
47+ [this ](const TOCItem* child)
48+ {
49+ return hasChildrenMatchingTheFilter (child);
50+ });
51+ }
52+
53+ bool FilteredTOCModel::itemPassesFilter (const TOCItem* item) const
54+ {
55+ auto similarity = fuzzCompareWithFilterString (item->text );
56+ double minSimilarity = 70 ;
57+
58+ return similarity >= minSimilarity;
59+ }
60+
61+ double FilteredTOCModel::fuzzCompareWithFilterString (QString str) const
62+ {
63+ // If the sorting string is a sub-string of str, return a high ratio
64+ auto leftSubstrPos = str.toLower ().indexOf (m_filterString.toLower ());
65+ if (leftSubstrPos != -1 )
66+ {
67+ // The further at the front, the better the ratio should be
68+ double ratio = 100 - leftSubstrPos;
69+ // A difference in length of the strings should reduce the score
70+ ratio -= std::abs (str.length () - m_filterString.length ()) * 0.1 ;
71+
72+ return ratio;
73+ }
74+
75+ return rapidfuzz::fuzz::ratio (m_filterString.toStdString (),
76+ str.toStdString ());
77+ }
78+
79+ } // namespace Okular
0 commit comments