Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qqmlsignalnames.cpp
Go to the documentation of this file.
1
// Copyright (C) 2023 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
5
#
include
"qqmlsignalnames_p.h"
6
#
include
<
iterator
>
7
#
include
<
algorithm
>
8
#
include
<
optional
>
9
#
include
<
string
>
10
11
QT_BEGIN_NAMESPACE
12
13
using
namespace
Qt::Literals;
14
15
static
constexpr
const
QLatin1String
On
(
"on"
);
16
static
constexpr
const
QLatin1String
Changed
(
"Changed"
);
17
18
static
constexpr
const
qsizetype
StrlenOn
= On.length();
19
static
constexpr
const
qsizetype
StrlenChanged
= Changed.length();
20
21
static
std
::
optional
<
qsizetype
>
firstLetterIdx
(QStringView name, qsizetype removePrefix = 0,
22
qsizetype removeSuffix = 0)
23
{
24
auto
end =
std
::prev(name.cend(), removeSuffix);
25
auto
result =
std
::find_if(
std
::next(name.cbegin(), removePrefix), end,
26
[](
const
QChar &c) {
return
c.isLetter(); });
27
if
(result != end)
28
return
std
::distance(name.begin(), result);
29
30
return
{};
31
}
32
33
static
std
::
optional
<
QChar
>
firstLetter
(QStringView name, qsizetype removePrefix = 0,
34
qsizetype removeSuffix = 0)
35
{
36
if
(
auto
idx = firstLetterIdx(name, removePrefix, removeSuffix))
37
return
name[*idx];
38
return
{};
39
}
40
41
enum
ChangeCase
{
ToUpper
,
ToLower
};
42
static
void
changeCaseOfFirstLetter
(QString &name,
ChangeCase
option, qsizetype removePrefix = 0,
43
qsizetype removeSuffix = 0)
44
{
45
auto
idx = firstLetterIdx(name, removePrefix, removeSuffix);
46
if
(!idx)
47
return
;
48
49
QChar &changeMe = name[*idx];
50
changeMe = option ==
ToUpper
? changeMe.toUpper() : changeMe.toLower();
51
};
52
53
static
std
::
optional
<
QString
>
toQStringData
(std::optional<QStringView> view)
54
{
55
if
(view)
56
return
view->toString();
57
return
std
::nullopt;
58
}
59
60
static
QByteArray
toUtf8Data
(QUtf8StringView view)
61
{
62
return
QByteArray(view.data(), view.size());
63
}
64
65
static
std
::
optional
<
QByteArray
>
toUtf8Data
(std::optional<QUtf8StringView> view)
66
{
67
if
(view)
68
return
toUtf8Data(*view);
69
return
std
::nullopt;
70
}
71
72
/*!
73
\internal
74
\class QQmlSignalNames
75
76
QQmlSignalNames contains a list of helper methods to manipulate signal names.
77
Always try to use the most specific one, as combining them might lead to incorrect
78
results like wrong upper/lower case, for example.
79
*/
80
81
/*!
82
\internal
83
Concatenate a prefix to a property name and uppercases the first letter of the property name.
84
*/
85
QString QQmlSignalNames::addPrefixToPropertyName(QStringView prefix, QStringView propertyName)
86
{
87
QString result = prefix.toString().append(propertyName);
88
changeCaseOfFirstLetter(result, ToUpper, prefix.size());
89
return
result;
90
}
91
92
QString QQmlSignalNames::propertyNameToChangedSignalName(QStringView property)
93
{
94
return
property.toString().append(Changed);
95
}
96
97
QByteArray QQmlSignalNames::propertyNameToChangedSignalName(QUtf8StringView property)
98
{
99
return
toUtf8Data(property).append(QByteArrayView(Changed));
100
}
101
102
QString QQmlSignalNames::propertyNameToChangedHandlerName(QStringView property)
103
{
104
return
propertyNameToChangedSignalName(signalNameToHandlerName(property));
105
}
106
107
template
<
typename
View>
108
std
::optional<View>
changedSignalNameToPropertyNameTemplate
(View changeSignal)
109
{
110
const
qsizetype changeSignalSize = changeSignal.size();
111
if
(changeSignalSize < StrlenChanged || changeSignal.last(StrlenChanged).compare(Changed) != 0)
112
return
std
::nullopt;
113
114
const
View result = changeSignal.sliced(0, changeSignalSize - StrlenChanged);
115
if
(!result.isEmpty())
116
return
result;
117
118
return
{};
119
}
120
121
/*!
122
\internal
123
Obtain a propertyName from its changed signal handler.
124
Do not call this on a value obtained from handlerNameToSignalName! Instead use
125
changedHandlerNameToPropertyName() directly. Otherwise you might end up with a wrong
126
capitalization of _Changed for "on_Changed", for example.
127
*/
128
129
std::optional<QString> QQmlSignalNames::changedSignalNameToPropertyName(QStringView signalName)
130
{
131
return
toQStringData(changedSignalNameToPropertyNameTemplate(signalName));
132
}
133
std::optional<QByteArray>
134
QQmlSignalNames::changedSignalNameToPropertyName(QUtf8StringView signalName)
135
{
136
return
toUtf8Data(changedSignalNameToPropertyNameTemplate(signalName));
137
}
138
139
/*!
140
\internal
141
Returns a property name from \a changedHandler.
142
This fails for property names starting with an upper-case letter, as it will lower-case it in the
143
process.
144
*/
145
std::optional<QString> QQmlSignalNames::changedHandlerNameToPropertyName(QStringView handler)
146
{
147
if
(!isChangedHandlerName(handler))
148
return
{};
149
150
if
(
auto
withoutChangedSuffix = changedSignalNameToPropertyName(handler)) {
151
return
handlerNameToSignalName(*withoutChangedSuffix);
152
}
153
return
{};
154
}
155
156
QString QQmlSignalNames::signalNameToHandlerName(QAnyStringView signal)
157
{
158
QString handlerName;
159
handlerName.reserve(StrlenOn + signal.length());
160
handlerName.append(On);
161
162
signal.visit([&handlerName](
auto
&&s) { handlerName.append(s); });
163
164
changeCaseOfFirstLetter(handlerName, ToUpper, StrlenOn);
165
return
handlerName;
166
}
167
168
enum
HandlerType
{
ChangedHandler
,
Handler
};
169
170
template
<
HandlerType
type>
171
static
std
::
optional
<
QString
>
handlerNameToSignalNameHelper
(QStringView handler)
172
{
173
if
(!QQmlSignalNames::isHandlerName(handler))
174
return
{};
175
176
QString signalName = handler.sliced(StrlenOn).toString();
177
Q_ASSERT(!signalName.isEmpty());
178
179
changeCaseOfFirstLetter(signalName,
ToLower
, 0, type ==
ChangedHandler
? StrlenChanged : 0);
180
return
signalName;
181
}
182
183
/*!
184
\internal
185
Returns a signal name from \a handlerName string. Do not use it on changed handlers, see
186
changedHandlerNameToSignalName for that!
187
*/
188
std::optional<QString> QQmlSignalNames::handlerNameToSignalName(QStringView handler)
189
{
190
return
handlerNameToSignalNameHelper<Handler>(handler);
191
}
192
193
/*!
194
\internal
195
Returns a signal name from \a handlerName string. Do not use it on changed handlers, see
196
changedHandlerNameToSignalName for that! Accepts improperly capitalized handler names and
197
incorrectly resolves signal names that start with '_' or '$'.
198
*/
199
std::optional<QString> QQmlSignalNames::badHandlerNameToSignalName(QStringView handler)
200
{
201
if
(handler.size() <= StrlenOn || !handler.startsWith(On))
202
return
{};
203
204
QString signalName = handler.sliced(StrlenOn).toString();
205
206
// This is quite wrong. But we need it for backwards compatibility.
207
signalName.front() = signalName.front().toLower();
208
209
return
signalName;
210
}
211
212
/*!
213
\internal
214
Returns a signal name from \a changedHandlerName string. Makes sure not to lowercase the 'C' from
215
Changed.
216
*/
217
std::optional<QString> QQmlSignalNames::changedHandlerNameToSignalName(QStringView handler)
218
{
219
return
handlerNameToSignalNameHelper<ChangedHandler>(handler);
220
}
221
222
bool
QQmlSignalNames::isChangedSignalName(QStringView signalName)
223
{
224
if
(signalName.size() <= StrlenChanged || !signalName.endsWith(Changed))
225
return
false
;
226
227
if
(
auto
letter = firstLetter(signalName, 0, StrlenChanged))
228
return
letter->isLower();
229
230
return
true
;
231
}
232
233
bool
QQmlSignalNames::isChangedHandlerName(QStringView signalName)
234
{
235
if
(signalName.size() <= (StrlenOn + StrlenChanged)
236
|| !signalName.startsWith(On)
237
|| !signalName.endsWith(Changed)) {
238
return
false
;
239
}
240
241
if
(
auto
letter = firstLetter(signalName, StrlenOn, StrlenChanged))
242
return
letter->isUpper();
243
244
return
true
;
245
}
246
247
bool
QQmlSignalNames::isHandlerName(QStringView signalName)
248
{
249
if
(signalName.size() <= StrlenOn || !signalName.startsWith(On))
250
return
false
;
251
252
if
(
auto
letter = firstLetter(signalName, StrlenOn))
253
return
letter->isUpper();
254
255
return
true
;
256
}
257
258
QT_END_NAMESPACE
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
toUtf8Data
static QByteArray toUtf8Data(QUtf8StringView view)
Definition
qqmlsignalnames.cpp:60
Changed
static constexpr const QLatin1String Changed("Changed")
On
static constexpr const QLatin1String On("on")
firstLetter
static std::optional< QChar > firstLetter(QStringView name, qsizetype removePrefix=0, qsizetype removeSuffix=0)
Definition
qqmlsignalnames.cpp:33
changeCaseOfFirstLetter
static void changeCaseOfFirstLetter(QString &name, ChangeCase option, qsizetype removePrefix=0, qsizetype removeSuffix=0)
Definition
qqmlsignalnames.cpp:42
toQStringData
static std::optional< QString > toQStringData(std::optional< QStringView > view)
Definition
qqmlsignalnames.cpp:53
ChangeCase
ChangeCase
Definition
qqmlsignalnames.cpp:41
ToLower
@ ToLower
Definition
qqmlsignalnames.cpp:41
ToUpper
@ ToUpper
Definition
qqmlsignalnames.cpp:41
firstLetterIdx
static std::optional< qsizetype > firstLetterIdx(QStringView name, qsizetype removePrefix=0, qsizetype removeSuffix=0)
Definition
qqmlsignalnames.cpp:21
StrlenOn
static constexpr const qsizetype StrlenOn
Definition
qqmlsignalnames.cpp:18
handlerNameToSignalNameHelper
static std::optional< QString > handlerNameToSignalNameHelper(QStringView handler)
Definition
qqmlsignalnames.cpp:171
HandlerType
HandlerType
Definition
qqmlsignalnames.cpp:168
Handler
@ Handler
Definition
qqmlsignalnames.cpp:168
ChangedHandler
@ ChangedHandler
Definition
qqmlsignalnames.cpp:168
StrlenChanged
static constexpr const qsizetype StrlenChanged
Definition
qqmlsignalnames.cpp:19
changedSignalNameToPropertyNameTemplate
std::optional< View > changedSignalNameToPropertyNameTemplate(View changeSignal)
Definition
qqmlsignalnames.cpp:108
qtdeclarative
src
qml
common
qqmlsignalnames.cpp
Generated on
for Qt by
1.18.0