File indexing completed on 2024-06-16 04:59:04
0001 /* 0002 SPDX-FileCopyrightText: 2021 Intevation GmbH 0003 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #pragma once 0009 0010 #include <Qt> 0011 0012 #include <vector> 0013 0014 class QAbstractItemModel; 0015 class QModelIndex; 0016 class QRegularExpression; 0017 class QString; 0018 0019 namespace MailCommon 0020 { 0021 /* This class allows filtering a hierarchical item model with path-like 0022 * patterns like "parent/sub" similar to file path globbing. 0023 * 0024 * The matching works as follows: 0025 * * The pattern is split into sub-patterns wherever "/" occurs. 0026 * * The sub-patterns are matched against each item and its ancestors. 0027 * * The pattern matches for an item if all sub-patterns match the item and 0028 * its ancestors. 0029 * * The sub-pattern matching uses wildcard matching with implied "*" before 0030 * and after each sub-pattern. For details see 0031 * QRegularExpression::wildcardToRegularExpression(). 0032 * 0033 * Examples: 0034 * * "foo" matches all items that contain "foo". 0035 * * "foo/bar" matches all items matching "bar" with parent items matching "foo". 0036 * * "foo/" matches all child items of items matching "foo". 0037 * * "/bar" matches all items matching "bar" which have a parent item. 0038 * * "foo//bar" matches all items matching "bar" with grandparents matching "foo". 0039 * 0040 * For more examples have a look at the tests in foldertreewidgettest.cpp. 0041 * 0042 * Design decisions: 0043 * * The original request was that "foo" should match items that contain "foo" 0044 * *and* their (direct?) child items, so that one can easily narrow down the 0045 * list of folders to the folders belonging to a subfolder tree, e.g. the 0046 * subfolder tree for "project foo". 0047 * I decided against this for the following reasons: 0048 * * The requested result can be achieved with "foo/". 0049 * * If there are multiple folders matching "foo" with a larger number of 0050 * subfolders, then it would not have been easy to select the wanted 0051 * folder matching "foo" because of all the subfolders that are also listed. 0052 * * I also think that the behavior of the original request isn't really 0053 * intuitive, at least for people who know file path globbing. 0054 */ 0055 class HierarchicalFolderMatcher 0056 { 0057 public: 0058 HierarchicalFolderMatcher(); 0059 0060 [[nodiscard]] bool isNull() const; 0061 0062 void setFilter(const QString &filter, Qt::CaseSensitivity caseSensitivity); 0063 0064 [[nodiscard]] bool matches(const QAbstractItemModel *model, const QModelIndex &start, int role = Qt::DisplayRole); 0065 0066 [[nodiscard]] QModelIndex findFirstMatch(const QAbstractItemModel *model, const QModelIndex &start, int role = Qt::DisplayRole); 0067 0068 private: 0069 std::vector<QRegularExpression> filterRegExps; 0070 }; 0071 }