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
qquickimageselector.cpp
Go to the documentation of this file.
1
// Copyright (C) 2022 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 reason:default
4
5
#
include
"qquickimageselector_p.h"
6
7
#
include
<
private
/
qqmlproperty_p
.
h
>
8
9
#
include
<
QtCore
/
qcache
.
h
>
10
#
include
<
QtCore
/
qdir
.
h
>
11
#
include
<
QtCore
/
qfileinfo
.
h
>
12
#
include
<
QtCore
/
qfileselector
.
h
>
13
#
include
<
QtCore
/
qloggingcategory
.
h
>
14
15
#
include
<
QtQml
/
qqmlcontext
.
h
>
16
#
include
<
QtQml
/
qqmlfile
.
h
>
17
18
#
include
<
algorithm
>
19
20
QT_BEGIN_NAMESPACE
21
22
Q_STATIC_LOGGING_CATEGORY
(lcQtQuickControlsImageSelector,
"qt.quick.controls.imageselector"
)
23
24
static
const
int
DEFAULT_CACHE
= 500;
25
26
static
inline
int
cacheSize
()
27
{
28
static
bool
ok =
false
;
29
static
const
int
size = qEnvironmentVariableIntValue(
"QT_QUICK_CONTROLS_IMAGESELECTOR_CACHE"
, &ok);
30
return
ok ? size :
DEFAULT_CACHE
;
31
}
32
33
// input: [focused, pressed]
34
// => [[focused, pressed], [pressed, focused], [focused], [pressed]]
35
static
QList
<
QStringList
>
permutations
(
const
QStringList &input,
int
count = -1)
36
{
37
if
(count == -1)
38
count = input.size();
39
40
QList<QStringList> output;
41
for
(
int
i = 0; i < input.size(); ++i) {
42
QStringList sub = input.mid(i, count);
43
44
if
(count > 1) {
45
if
(i + count > input.size())
46
sub += input.mid(0, count - i + 1);
47
48
std
::sort(sub.begin(), sub.end());
49
do
{
50
if
(!sub.isEmpty())
51
output += sub;
52
}
while
(
std
::next_permutation(sub.begin(), sub.end()));
53
}
else
{
54
output += sub;
55
}
56
57
if
(count == input.size())
58
break
;
59
}
60
61
if
(count > 1)
62
output += permutations(input, --count);
63
64
return
output;
65
}
66
67
static
QString
findFile
(
const
QDir &dir,
const
QString &baseName,
const
QStringList &extensions)
68
{
69
for
(
const
QString &ext : extensions) {
70
QString filePath = dir.filePath(baseName + QLatin1Char(
'.'
) + ext);
71
if
(QFile::exists(filePath))
72
return
QFileSelector().select(filePath);
73
}
74
// return an empty string to indicate that the lookup has been done
75
// even if no matching asset was found
76
return
QLatin1String(
""
);
77
}
78
79
QQuickImageSelector::QQuickImageSelector(QObject *parent)
80
: QObject(parent),
81
m_cache(
cacheSize
(
)
> 0)
82
{
83
}
84
85
QUrl QQuickImageSelector::source()
const
86
{
87
return
m_source;
88
}
89
90
void
QQuickImageSelector::setSource(
const
QUrl &source)
91
{
92
if
(m_property.isValid())
93
QQmlPropertyPrivate::write(m_property, source, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
94
if
(m_source == source)
95
return
;
96
97
m_source = source;
98
emit sourceChanged();
99
}
100
101
QString QQuickImageSelector::name()
const
102
{
103
return
m_name;
104
}
105
106
void
QQuickImageSelector::setName(
const
QString &name)
107
{
108
if
(m_name == name)
109
return
;
110
111
m_name = name;
112
if
(m_complete)
113
updateSource();
114
}
115
116
QString QQuickImageSelector::path()
const
117
{
118
return
m_path;
119
}
120
121
void
QQuickImageSelector::setPath(
const
QString &path)
122
{
123
if
(m_path == path)
124
return
;
125
126
m_path = path;
127
if
(m_complete)
128
updateSource();
129
}
130
131
QVariantList QQuickImageSelector::states()
const
132
{
133
return
m_allStates;
134
}
135
136
void
QQuickImageSelector::setStates(
const
QVariantList &states)
137
{
138
if
(m_allStates == states)
139
return
;
140
141
m_allStates = states;
142
if
(updateActiveStates() && m_complete)
143
updateSource();
144
}
145
146
QString QQuickImageSelector::separator()
const
147
{
148
return
m_separator;
149
}
150
151
void
QQuickImageSelector::setSeparator(
const
QString &separator)
152
{
153
if
(m_separator == separator)
154
return
;
155
156
m_separator = separator;
157
if
(m_complete)
158
updateSource();
159
}
160
161
bool
QQuickImageSelector::cache()
const
162
{
163
return
m_cache;
164
}
165
166
void
QQuickImageSelector::setCache(
bool
cache)
167
{
168
m_cache = cache;
169
}
170
171
void
QQuickImageSelector::write(
const
QVariant &value)
172
{
173
setUrl(value.toUrl());
174
}
175
176
void
QQuickImageSelector::setTarget(
const
QQmlProperty &property)
177
{
178
m_property = property;
179
}
180
181
void
QQuickImageSelector::classBegin()
182
{
183
}
184
185
void
QQuickImageSelector::componentComplete()
186
{
187
setUrl(m_property.read().toUrl());
188
m_complete =
true
;
189
updateSource();
190
}
191
192
QStringList QQuickImageSelector::fileExtensions()
const
193
{
194
static
const
QStringList extensions = QStringList() << QStringLiteral(
"png"
);
195
return
extensions;
196
}
197
198
QString QQuickImageSelector::cacheKey()
const
199
{
200
if
(!m_cache)
201
return
QString();
202
203
return
m_path + m_name + m_activeStates.join(m_separator);
204
}
205
206
void
QQuickImageSelector::updateSource()
207
{
208
static
QCache<QString, QString> cache(
cacheSize
(
)
);
209
210
const
QString key = cacheKey();
211
212
QString bestFilePath;
213
214
if
(m_cache) {
215
QString *cachedPath = cache.object(key);
216
if
(cachedPath)
217
bestFilePath = *cachedPath;
218
}
219
220
// note: a cached file path may be empty
221
if
(bestFilePath.isNull()) {
222
QDir dir(m_path);
223
int
bestScore = -1;
224
225
const
QStringList extensions = fileExtensions();
226
227
const
QList<QStringList> statePerms = permutations(m_activeStates);
228
for
(
const
QStringList &perm : statePerms) {
229
const
QString filePath = findFile(dir, m_name + m_separator + perm.join(m_separator), extensions);
230
if
(!filePath.isEmpty()) {
231
int
score = calculateScore(perm);
232
if
(score > bestScore) {
233
bestScore = score;
234
bestFilePath = filePath;
235
}
236
}
237
}
238
239
if
(bestFilePath.isEmpty())
240
bestFilePath = findFile(dir, m_name, extensions);
241
242
if
(m_cache)
243
cache.insert(key,
new
QString(bestFilePath));
244
}
245
246
qCDebug(lcQtQuickControlsImageSelector) << m_name << m_activeStates <<
"->"
<< bestFilePath;
247
248
if
(bestFilePath.startsWith(QLatin1Char(
':'
)))
249
setSource(QUrl(QLatin1String(
"qrc"
) + bestFilePath));
250
else
251
setSource(QUrl::fromLocalFile(bestFilePath));
252
}
253
254
void
QQuickImageSelector::setUrl(
const
QUrl &url)
255
{
256
// Allow passing a relative path as e.g. QQuickImageBase::loadPixmap does.
257
QUrl resolvedUrl = url;
258
if
(url.isRelative()) {
259
auto
*ourQmlcontext = qmlContext(
this
);
260
if
(ourQmlcontext)
261
resolvedUrl = ourQmlcontext->resolvedUrl(url);
262
}
263
264
const
QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(resolvedUrl));
265
setName(fileInfo.fileName());
266
setPath(fileInfo.path());
267
}
268
269
bool
QQuickImageSelector::updateActiveStates()
270
{
271
QStringList active;
272
for
(
const
QVariant &v : std::as_const(m_allStates)) {
273
const
QVariantMap state = v.toMap();
274
if
(state.isEmpty())
275
continue
;
276
auto
it = state.begin();
277
if
(it.value().toBool())
278
active += it.key();
279
}
280
281
if
(m_activeStates == active)
282
return
false
;
283
284
m_activeStates = active;
285
return
true
;
286
}
287
288
int
QQuickImageSelector::calculateScore(
const
QStringList &states)
const
289
{
290
int
score = 0;
291
for
(
int
i = 0; i < states.size(); ++i)
292
score += (m_activeStates.size() - m_activeStates.indexOf(states.at(i))) << 1;
293
return
score;
294
}
295
296
QQuickNinePatchImageSelector
::QQuickNinePatchImageSelector(QObject *parent)
297
: QQuickImageSelector(parent)
298
{
299
}
300
301
QStringList
QQuickNinePatchImageSelector
::
fileExtensions
()
const
302
{
303
static
const
QStringList extensions = QStringList() << QStringLiteral(
"9.png"
) << QStringLiteral(
"png"
);
304
return
extensions;
305
}
306
307
QQuickAnimatedImageSelector
::QQuickAnimatedImageSelector(QObject *parent)
308
: QQuickImageSelector(parent)
309
{
310
}
311
312
QStringList
QQuickAnimatedImageSelector
::
fileExtensions
()
const
313
{
314
static
const
QStringList extensions = QStringList() << QStringLiteral(
"webp"
) << QStringLiteral(
"gif"
);
315
return
extensions;
316
}
317
318
QT_END_NAMESPACE
319
320
#
include
"moc_qquickimageselector_p.cpp"
QQuickAnimatedImageSelector
Definition
qquickimageselector_p.h:108
QQuickAnimatedImageSelector::fileExtensions
QStringList fileExtensions() const override
Definition
qquickimageselector.cpp:312
QQuickNinePatchImageSelector
Definition
qquickimageselector_p.h:95
QQuickNinePatchImageSelector::fileExtensions
QStringList fileExtensions() const override
Definition
qquickimageselector.cpp:301
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
Q_STATIC_LOGGING_CATEGORY
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
cacheSize
static int cacheSize()
Definition
qquickimageselector.cpp:26
permutations
static QList< QStringList > permutations(const QStringList &input, int count=-1)
Definition
qquickimageselector.cpp:35
DEFAULT_CACHE
static QT_BEGIN_NAMESPACE const int DEFAULT_CACHE
Definition
qquickimageselector.cpp:24
findFile
static QString findFile(const QDir &dir, const QString &baseName, const QStringList &extensions)
Definition
qquickimageselector.cpp:67
qtdeclarative
src
quickcontrolsimpl
qquickimageselector.cpp
Generated on
for Qt by
1.18.0