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