Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlpreviewblacklist.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
6
8
9void QQmlPreviewBlacklist::blacklist(const QString &path)
10{
11 if (!path.isEmpty())
12 m_root.insert(path, 0);
13}
14
15void QQmlPreviewBlacklist::whitelist(const QString &path)
16{
17 if (!path.isEmpty())
18 m_root.remove(path, 0);
19}
20
21bool QQmlPreviewBlacklist::isBlacklisted(const QString &path) const
22{
23 return path.isEmpty() ? true : m_root.findPrefix(path, 0) == Node::MatchedLeaf;
24}
25
26void QQmlPreviewBlacklist::clear()
27{
28 m_root = Node();
29}
30
31QQmlPreviewBlacklist::Node::Node()
32{
33}
34
35QQmlPreviewBlacklist::Node::Node(const QQmlPreviewBlacklist::Node &other) :
36 m_mine(other.m_mine), m_isLeaf(other.m_isLeaf)
37{
38 for (auto it = other.m_next.begin(), end = other.m_next.end(); it != end; ++it)
39 m_next.insert(it.key(), new Node(**it));
40}
41
42QQmlPreviewBlacklist::Node::Node(QQmlPreviewBlacklist::Node &&other) noexcept
43{
44 m_mine.swap(other.m_mine);
45 m_next.swap(other.m_next);
46 m_isLeaf = other.m_isLeaf;
47}
48
49QQmlPreviewBlacklist::Node::~Node()
50{
51 qDeleteAll(m_next);
52}
53
54QQmlPreviewBlacklist::Node &QQmlPreviewBlacklist::Node::operator=(
55 const QQmlPreviewBlacklist::Node &other)
56{
57 if (&other != this) {
58 m_mine = other.m_mine;
59 for (auto it = other.m_next.begin(), end = other.m_next.end(); it != end; ++it)
60 m_next.insert(it.key(), new Node(**it));
61 m_isLeaf = other.m_isLeaf;
62 }
63 return *this;
64}
65
66QQmlPreviewBlacklist::Node &QQmlPreviewBlacklist::Node::operator=(
67 QQmlPreviewBlacklist::Node &&other) noexcept
68{
69 if (&other != this) {
70 m_mine.swap(other.m_mine);
71 m_next.swap(other.m_next);
72 m_isLeaf = other.m_isLeaf;
73 }
74 return *this;
75}
76
77void QQmlPreviewBlacklist::Node::split(QString::iterator it, QString::iterator end)
78{
79 QString existing;
80 existing.resize(end - it - 1);
81 std::copy(it + 1, end, existing.begin());
82
83 Node *node = new Node(existing, m_next, m_isLeaf);
84 m_next.clear();
85 m_next.insert(*it, node);
86 m_mine.resize(it - m_mine.begin());
87 m_isLeaf = false;
88}
89
90void QQmlPreviewBlacklist::Node::insert(const QString &path, int offset)
91{
92 for (auto it = m_mine.begin(), end = m_mine.end(); it != end; ++it) {
93 if (offset == path.size()) {
94 split(it, end);
95 m_isLeaf = true;
96 return;
97 }
98
99 if (path.at(offset) != *it) {
100 split(it, end);
101
102 QString inserted;
103 inserted.resize(path.size() - offset - 1);
104 std::copy(path.begin() + offset + 1, path.end(), inserted.begin());
105 m_next.insert(path.at(offset), new Node(inserted));
106 return;
107 }
108
109 ++offset;
110 }
111
112 if (offset == path.size()) {
113 m_isLeaf = true;
114 return;
115 }
116
117 Node *&node = m_next[path.at(offset++)];
118 if (node == nullptr) {
119 QString inserted;
120 inserted.resize(path.size() - offset);
121 std::copy(path.begin() + offset, path.end(), inserted.begin());
122 node = new Node(inserted);
123 } else {
124 node->insert(path, offset);
125 }
126}
127
128void QQmlPreviewBlacklist::Node::remove(const QString &path, int offset)
129{
130 for (auto it = m_mine.begin(), end = m_mine.end(); it != end; ++it) {
131 if (offset == path.size() || path.at(offset) != *it) {
132 split(it, end);
133 return;
134 }
135 ++offset;
136 }
137
138 m_isLeaf = false;
139 if (offset == path.size())
140 return;
141
142 Node *&node = m_next[path.at(offset++)];
143 if (node) {
144 node->remove(path, offset);
145 } else {
146 QString inserted;
147 inserted.resize(path.size() - offset);
148 std::copy(path.begin() + offset, path.end(), inserted.begin());
149 node = new Node(inserted, {}, false);
150 }
151}
152
153QQmlPreviewBlacklist::Node::PrefixResult QQmlPreviewBlacklist::Node::findPrefix(
154 const QString &path, int offset) const
155{
156 if (offset == path.size()) {
157 if (!m_mine.isEmpty())
158 return Unmatched;
159 return m_isLeaf ? MatchedLeaf : MatchedBranch;
160 }
161
162 for (auto it = m_mine.begin(), end = m_mine.end(); it != end; ++it) {
163 if (path.at(offset) != *it)
164 return Unmatched;
165
166 if (++offset == path.size()) {
167 if (++it != end)
168 return Unmatched;
169 return m_isLeaf ? MatchedLeaf : MatchedBranch;
170 }
171 }
172
173 const QChar c = path.at(offset);
174 const auto it = m_next.find(c);
175 if (it != m_next.end()) {
176 const PrefixResult result = (*it)->findPrefix(path, offset + 1);
177 if (result != Unmatched)
178 return result;
179 }
180
181 if (c == '/')
182 return m_isLeaf ? MatchedLeaf : MatchedBranch;
183
184 return Unmatched;
185}
186
187QQmlPreviewBlacklist::Node::Node(const QString &mine,
188 const QHash<QChar, QQmlPreviewBlacklist::Node *> &next,
189 bool isLeaf)
190 : m_mine(mine), m_next(next), m_isLeaf(isLeaf)
191{
192}
193
194QT_END_NAMESPACE
Combined button and popup list for selecting options.