Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
5
6#include <QtCore/qdir.h>
7#include <QtCore/qfileinfo.h>
8#include <QtCore/qcache.h>
9#include <QtCore/qloggingcategory.h>
10#include <QtCore/qfileselector.h>
11#include <QtQml/qqmlfile.h>
12#include <QtQml/private/qqmlproperty_p.h>
13#include <algorithm>
14
16
17Q_LOGGING_CATEGORY(lcQtQuickControlsImageSelector, "qt.quick.controls.imageselector")
18
19static const int DEFAULT_CACHE = 500;
20
21static inline int cacheSize()
22{
23 static bool ok = false;
24 static const int size = qEnvironmentVariableIntValue("QT_QUICK_CONTROLS_IMAGESELECTOR_CACHE", &ok);
25 return ok ? size : DEFAULT_CACHE;
26}
27
28// input: [focused, pressed]
29// => [[focused, pressed], [pressed, focused], [focused], [pressed]]
30static QList<QStringList> permutations(const QStringList &input, int count = -1)
31{
32 if (count == -1)
33 count = input.size();
34
35 QList<QStringList> output;
36 for (int i = 0; i < input.size(); ++i) {
37 QStringList sub = input.mid(i, count);
38
39 if (count > 1) {
40 if (i + count > input.size())
41 sub += input.mid(0, count - i + 1);
42
43 std::sort(sub.begin(), sub.end());
44 do {
45 if (!sub.isEmpty())
46 output += sub;
47 } while (std::next_permutation(sub.begin(), sub.end()));
48 } else {
49 output += sub;
50 }
51
52 if (count == input.size())
53 break;
54 }
55
56 if (count > 1)
58
59 return output;
60}
61
62static QString findFile(const QDir &dir, const QString &baseName, const QStringList &extensions)
63{
64 for (const QString &ext : extensions) {
65 QString filePath = dir.filePath(baseName + QLatin1Char('.') + ext);
66 if (QFile::exists(filePath))
67 return QFileSelector().select(filePath);
68 }
69 // return an empty string to indicate that the lookup has been done
70 // even if no matching asset was found
71 return QLatin1String("");
72}
73
75 : QObject(parent),
76 m_cache(cacheSize() > 0)
77{
78}
79
81{
82 return m_source;
83}
84
86{
87 if (m_property.isValid())
89 if (m_source == source)
90 return;
91
92 m_source = source;
94}
95
97{
98 return m_name;
99}
100
102{
103 if (m_name == name)
104 return;
105
106 m_name = name;
107 if (m_complete)
108 updateSource();
109}
110
112{
113 return m_path;
114}
115
117{
118 if (m_path == path)
119 return;
120
121 m_path = path;
122 if (m_complete)
123 updateSource();
124}
125
127{
128 return m_allStates;
129}
130
132{
133 if (m_allStates == states)
134 return;
135
136 m_allStates = states;
137 if (updateActiveStates() && m_complete)
138 updateSource();
139}
140
142{
143 return m_separator;
144}
145
147{
148 if (m_separator == separator)
149 return;
150
151 m_separator = separator;
152 if (m_complete)
153 updateSource();
154}
155
157{
158 return m_cache;
159}
160
162{
163 m_cache = cache;
164}
165
167{
168 setUrl(value.toUrl());
169}
170
172{
173 m_property = property;
174}
175
179
181{
182 setUrl(m_property.read().toUrl());
183 m_complete = true;
184 updateSource();
185}
186
188{
189 static const QStringList extensions = QStringList() << QStringLiteral("png");
190 return extensions;
191}
192
194{
195 if (!m_cache)
196 return QString();
197
198 return m_path + m_name + m_activeStates.join(m_separator);
199}
200
202{
203 static QCache<QString, QString> cache(cacheSize());
204
205 const QString key = cacheKey();
206
207 QString bestFilePath;
208
209 if (m_cache) {
210 QString *cachedPath = cache.object(key);
211 if (cachedPath)
212 bestFilePath = *cachedPath;
213 }
214
215 // note: a cached file path may be empty
216 if (bestFilePath.isNull()) {
217 QDir dir(m_path);
218 int bestScore = -1;
219
220 const QStringList extensions = fileExtensions();
221
222 const QList<QStringList> statePerms = permutations(m_activeStates);
223 for (const QStringList &perm : statePerms) {
224 const QString filePath = findFile(dir, m_name + m_separator + perm.join(m_separator), extensions);
225 if (!filePath.isEmpty()) {
226 int score = calculateScore(perm);
227 if (score > bestScore) {
228 bestScore = score;
229 bestFilePath = filePath;
230 }
231 }
232 }
233
234 if (bestFilePath.isEmpty())
235 bestFilePath = findFile(dir, m_name, extensions);
236
237 if (m_cache)
238 cache.insert(key, new QString(bestFilePath));
239 }
240
241 qCDebug(lcQtQuickControlsImageSelector) << m_name << m_activeStates << "->" << bestFilePath;
242
243 if (bestFilePath.startsWith(QLatin1Char(':')))
244 setSource(QUrl(QLatin1String("qrc") + bestFilePath));
245 else
246 setSource(QUrl::fromLocalFile(bestFilePath));
247}
248
250{
252 setName(fileInfo.fileName());
253 setPath(fileInfo.path());
254}
255
257{
258 QStringList active;
259 for (const QVariant &v : std::as_const(m_allStates)) {
260 const QVariantMap state = v.toMap();
261 if (state.isEmpty())
262 continue;
263 auto it = state.begin();
264 if (it.value().toBool())
265 active += it.key();
266 }
267
268 if (m_activeStates == active)
269 return false;
270
271 m_activeStates = active;
272 return true;
273}
274
276{
277 int score = 0;
278 for (int i = 0; i < states.size(); ++i)
279 score += (m_activeStates.size() - m_activeStates.indexOf(states.at(i))) << 1;
280 return score;
281}
282
287
289{
290 static const QStringList extensions = QStringList() << QStringLiteral("9.png") << QStringLiteral("png");
291 return extensions;
292}
293
298
300{
301 static const QStringList extensions = QStringList() << QStringLiteral("webp") << QStringLiteral("gif");
302 return extensions;
303}
304
306
307#include "moc_qquickimageselector_p.cpp"
\inmodule QtCore
Definition qdir.h:20
QString fileName() const
QString path() const
Returns the path of the file system entry this QFileInfo refers to, excluding the entry's name.
\inmodule QtCore
QString select(const QString &filePath) const
This function returns the selected version of the path, based on the conditions at runtime.
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
\inmodule QtCore
Definition qobject.h:103
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to \l{QFile}.
Definition qqmlfile.cpp:742
static bool write(QObject *, const QQmlPropertyData &, const QVariant &, const QQmlRefPointer< QQmlContextData > &, QQmlPropertyData::WriteFlags flags={})
The QQmlProperty class abstracts accessing properties on objects created from QML.
bool isValid() const
Returns true if the QQmlProperty refers to a valid property, otherwise false.
QVariant read() const
Returns the property value.
QQuickAnimatedImageSelector(QObject *parent=nullptr)
QStringList fileExtensions() const override
QQuickImageSelector(QObject *parent=nullptr)
void setSource(const QUrl &source)
void setPath(const QString &path)
int calculateScore(const QStringList &states) const
void write(const QVariant &value) override
This method will be called when a new value is assigned to the property being intercepted.
void setName(const QString &name)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void classBegin() override
Invoked after class creation, but before any properties have been set.
virtual QStringList fileExtensions() const
void setStates(const QVariantList &states)
void setSeparator(const QString &separator)
void setTarget(const QQmlProperty &property) override
Set the target property for the value interceptor.
void setUrl(const QUrl &url)
QQuickNinePatchImageSelector(QObject *parent=nullptr)
QStringList fileExtensions() const override
iterator begin()
Definition qset.h:136
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3368
\inmodule QtCore
Definition qvariant.h:65
QUrl toUrl() const
Returns the variant as a QUrl if the variant has userType() \l QMetaType::QUrl; otherwise returns an ...
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
else opt state
[0]
Combined button and popup list for selecting options.
QList< QString > QStringList
Constructs a string list that contains the given string, str.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter * sub
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLsizei const GLfloat * v
[13]
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLuint name
GLsizei GLsizei GLchar * source
GLsizei const GLchar *const * path
GLenum GLenum GLenum input
GLuint * states
static quint64 cacheSize()
static int cacheSize()
static QList< QStringList > permutations(const QStringList &input, int count=-1)
static QT_BEGIN_NAMESPACE const int DEFAULT_CACHE
static QString findFile(const QDir &dir, const QString &baseName, const QStringList &extensions)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define emit
QT_BEGIN_NAMESPACE typedef uchar * output
const char property[13]
Definition qwizard.cpp:101
QUrl url("example.com")
[constructor-url-reference]
QString dir
[11]
\inmodule QtCore \reentrant
Definition qchar.h:18