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
qqmlfileselector.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 BlackBerry Limited. All rights reserved.
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 <QtCore/QFileSelector>
6#include <QtQml/QQmlAbstractUrlInterceptor>
7#include <QtQml/private/qqmlengine_p.h>
8#include <QtQml/private/qqmlapplicationengine_p.h>
9#include <qobjectdefs.h>
12#include "qqmlengine_p.h"
13#include <QDebug>
14
16
17/*!
18 \class QQmlFileSelector
19 \since 5.2
20 \inmodule QtQml
21 \brief A class for applying a QFileSelector to QML file loading.
22
23 QQmlFileSelector will automatically apply a QFileSelector to
24 qml file and asset paths.
25
26 It is used as follows:
27
28 \code
29 QQmlEngine engine;
30 QQmlFileSelector* selector = new QQmlFileSelector(&engine);
31 \endcode
32
33 Then you can swap out files like so:
34 \code
35 main.qml
36 Component.qml
37 asset.png
38 +unix/Component.qml
39 +mac/asset.png
40 \endcode
41
42 In this example, main.qml will normally use Component.qml for the Component type. However on a
43 unix platform, the unix selector will be present and the +unix/Component.qml version will be
44 used instead. Note that this acts like swapping out Component.qml with +unix/Component.qml, so
45 when using Component.qml you should not need to alter any paths based on which version was
46 selected.
47
48 For example, to pass the "asset.png" file path around you would refer to it just as "asset.png" in
49 all of main.qml, Component.qml, and +linux/Component.qml. It will be replaced with +mac/asset.png
50 on Mac platforms in all cases.
51
52 For a list of available selectors, see \c QFileSelector.
53
54 Your platform may also provide additional selectors for you to use. As specified by QFileSelector,
55 directories used for selection must start with a '+' character, so you will not accidentally
56 trigger this feature unless you have directories with such names inside your project.
57
58 If a new QQmlFileSelector is set on the engine, the old one will be replaced.
59 */
60
61/*!
62 Creates a new QQmlFileSelector with parent object \a parent, which includes
63 its own QFileSelector. \a engine is the QQmlEngine you wish to apply file
64 selectors to. It will also take ownership of the QQmlFileSelector.
65*/
66
67QQmlFileSelector::QQmlFileSelector(QQmlEngine* engine, QObject* parent)
68 : QObject(*(new QQmlFileSelectorPrivate), parent)
69{
70 Q_D(QQmlFileSelector);
71 d->engine = engine;
72 d->engine->addUrlInterceptor(d->myInstance.data());
73}
74
75/*!
76 Destroys the QQmlFileSelector object.
77*/
78QQmlFileSelector::~QQmlFileSelector()
79{
80 Q_D(QQmlFileSelector);
81 if (d->engine) {
82 d->engine->removeUrlInterceptor(d->myInstance.data());
83 d->engine = nullptr;
84 }
85}
86
87/*!
88 \since 5.7
89 Returns the QFileSelector instance used by the QQmlFileSelector.
90*/
91QFileSelector *QQmlFileSelector::selector() const noexcept
92{
93 Q_D(const QQmlFileSelector);
94 return d->selector;
95}
96
97QQmlFileSelectorPrivate::QQmlFileSelectorPrivate()
98{
99 Q_Q(QQmlFileSelector);
100 ownSelector = true;
101 selector = new QFileSelector(q);
102 myInstance.reset(new QQmlFileSelectorInterceptor(this));
103}
104
105QQmlFileSelectorPrivate::~QQmlFileSelectorPrivate()
106{
107 if (ownSelector)
108 delete selector;
109}
110
111/*!
112 Sets the QFileSelector instance for use by the QQmlFileSelector to \a selector.
113 QQmlFileSelector does not take ownership of the new QFileSelector. To reset QQmlFileSelector
114 to use its internal QFileSelector instance, call setSelector(\nullptr).
115*/
116
117void QQmlFileSelector::setSelector(QFileSelector *selector)
118{
119 Q_D(QQmlFileSelector);
120 if (selector) {
121 if (d->ownSelector) {
122 delete d->selector;
123 d->ownSelector = false;
124 }
125 d->selector = selector;
126 } else {
127 if (!d->ownSelector) {
128 d->ownSelector = true;
129 d->selector = new QFileSelector(this);
130 } // Do nothing if already using internal selector
131 }
132}
133
134/*!
135 Adds extra selectors contained in \a strings to the current QFileSelector being used.
136 Use this when extra selectors are all you need to avoid having to create your own
137 QFileSelector instance.
138*/
139void QQmlFileSelector::setExtraSelectors(const QStringList &strings)
140{
141 Q_D(QQmlFileSelector);
142 d->selector->setExtraSelectors(strings);
143}
144
145#if QT_DEPRECATED_SINCE(6, 0)
146/*!
147 \deprecated [6.0] The file selector should not be accessed after it
148 is set. It may be in use. See below for further details.
149
150 Gets the QQmlFileSelector currently active on the target \a engine.
151
152 This method is deprecated. You should not retrieve the files selector from an
153 engine after setting it. It may be in use.
154
155 If the \a engine passed here is a QQmlApplicationEngine that hasn't loaded any
156 QML files, yet, it will be initialized. Any later calls to
157 QQmlApplicationEngine::setExtraFileSelectors() will have no effect.
158
159 \sa QQmlApplicationEngine
160*/
161QQmlFileSelector* QQmlFileSelector::get(QQmlEngine* engine)
162{
163 QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
164
165 if (qobject_cast<QQmlApplicationEngine *>(engine)) {
166 auto *appEnginePrivate = static_cast<QQmlApplicationEnginePrivate *>(enginePrivate);
167 appEnginePrivate->ensureInitialized();
168 }
169
170 const QUrl nonEmptyInvalid(QLatin1String(":"));
171 const auto interceptors = QQmlTypeLoader::get(engine)->urlInterceptors();
172 for (QQmlAbstractUrlInterceptor *interceptor : interceptors) {
173 const QUrl result = interceptor->intercept(
174 nonEmptyInvalid, QQmlAbstractUrlInterceptor::UrlString);
175 if (result.scheme() == QLatin1String("type")
176 && result.path() == QLatin1String("fileselector")) {
177 return static_cast<QQmlFileSelectorInterceptor *>(interceptor)->d->q_func();
178 }
179 }
180 return nullptr;
181}
182#endif
183
184/*!
185 \internal
186*/
187QQmlFileSelectorInterceptor::QQmlFileSelectorInterceptor(QQmlFileSelectorPrivate* pd)
188 : d(pd)
189{
190}
191
192/*!
193 \internal
194*/
195QUrl QQmlFileSelectorInterceptor::intercept(const QUrl &path, DataType type)
196{
197 if (!path.isEmpty() && !path.isValid())
198 return QUrl(QLatin1String("type:fileselector"));
199
200 return type == QQmlAbstractUrlInterceptor::QmldirFile
201 ? path // Don't intercept qmldir files, to prevent double interception
202 : d->selector->select(path);
203}
204
205QT_END_NAMESPACE
206
207#include "moc_qqmlfileselector.cpp"
Combined button and popup list for selecting options.