qfileselector.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/corelib/io/qfileselector.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/***************************************************************************-
2**-
3** Copyright (C) 2013 BlackBerry Limited. All rights reserved.-
4** Copyright (C) 2016 Intel Corporation.-
5** Contact: https://www.qt.io/licensing/-
6**-
7** This file is part of the QtCore module of the Qt Toolkit.-
8**-
9** $QT_BEGIN_LICENSE:LGPL$-
10** Commercial License Usage-
11** Licensees holding valid commercial Qt licenses may use this file in-
12** accordance with the commercial license agreement provided with the-
13** Software or, alternatively, in accordance with the terms contained in-
14** a written agreement between you and The Qt Company. For licensing terms-
15** and conditions see https://www.qt.io/terms-conditions. For further-
16** information use the contact form at https://www.qt.io/contact-us.-
17**-
18** GNU Lesser General Public License Usage-
19** Alternatively, this file may be used under the terms of the GNU Lesser-
20** General Public License version 3 as published by the Free Software-
21** Foundation and appearing in the file LICENSE.LGPL3 included in the-
22** packaging of this file. Please review the following information to-
23** ensure the GNU Lesser General Public License version 3 requirements-
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
25**-
26** GNU General Public License Usage-
27** Alternatively, this file may be used under the terms of the GNU-
28** General Public License version 2.0 or (at your option) the GNU General-
29** Public license version 3 or any later version approved by the KDE Free-
30** Qt Foundation. The licenses are as published by the Free Software-
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
32** included in the packaging of this file. Please review the following-
33** information to ensure the GNU General Public License requirements will-
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
35** https://www.gnu.org/licenses/gpl-3.0.html.-
36**-
37** $QT_END_LICENSE$-
38**-
39****************************************************************************/-
40-
41#include "qfileselector.h"-
42#include "qfileselector_p.h"-
43-
44#include <QtCore/QFile>-
45#include <QtCore/QDir>-
46#include <QtCore/QMutex>-
47#include <QtCore/QMutexLocker>-
48#include <QtCore/QUrl>-
49#include <QtCore/QFileInfo>-
50#include <QtCore/QLocale>-
51#include <QtCore/QDebug>-
52-
53QT_BEGIN_NAMESPACE-
54-
55//Environment variable to allow tooling full control of file selectors-
56static const char env_override[] = "QT_NO_BUILTIN_SELECTORS";-
57-
58static const ushort selectorIndicator = '+';-
59-
60Q_GLOBAL_STATIC(QFileSelectorSharedData, sharedData);
executed 1 time by 1 test: end of block
Executed by:
  • tst_qfileselectors - unknown status
executed 1 time by 1 test: guard.store(QtGlobalStatic::Destroyed);
Executed by:
  • tst_qfileselectors - unknown status
executed 50 times by 1 test: return &holder.value;
Executed by:
  • tst_QFileSelector
guard.load() =...c::InitializedDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_qfileselectors - unknown status
FALSEnever evaluated
0-50
61static QBasicMutex sharedDataMutex;-
62-
63QFileSelectorPrivate::QFileSelectorPrivate()-
64 : QObjectPrivate()-
65{-
66}
executed 19 times by 1 test: end of block
Executed by:
  • tst_QFileSelector
19
67-
68/*!-
69 \class QFileSelector-
70 \inmodule QtCore-
71 \brief QFileSelector provides a convenient way of selecting file variants.-
72 \since 5.2-
73-
74 QFileSelector is a convenience for selecting file variants based on platform or device-
75 characteristics. This allows you to develop and deploy one codebase containing all the-
76 different variants more easily in some circumstances, such as when the correct variant cannot-
77 be determined during the deploy step.-
78-
79 \section1 Using QFileSelector-
80-
81 If you always use the same file you do not need to use QFileSelector.-
82-
83 Consider the following example usage, where you want to use different settings files on-
84 different locales. You might select code between locales like this:-
85-
86 \code-
87 QString defaultsBasePath = "data/";-
88 QString defaultsPath = defaultsBasePath + "defaults.conf";-
89 QString localizedPath = defaultsBasePath-
90 + QString("%1/defaults.conf").arg(QLocale().name());-
91 if (QFile::exists(localizedPath))-
92 defaultsPath = localizedPath;-
93 QFile defaults(defaultsPath);-
94 \endcode-
95-
96 Similarly, if you want to pick a different data file based on target platform,-
97 your code might look something like this:-
98 \code-
99 QString defaultsPath = "data/defaults.conf";-
100#if defined(Q_OS_ANDROID)-
101 defaultsPath = "data/android/defaults.conf";-
102#elif defined(Q_OS_IOS)-
103 defaultsPath = "data/ios/defaults.conf";-
104#endif-
105 QFile defaults(defaultsPath);-
106 \endcode-
107-
108 QFileSelector provides a convenient alternative to writing such boilerplate code, and in the-
109 latter case it allows you to start using an platform-specific configuration without a recompile.-
110 QFileSelector also allows for chaining of multiple selectors in a convenient way, for example-
111 selecting a different file only on certain combinations of platform and locale. For example, to-
112 select based on platform and/or locale, the code is as follows:-
113-
114 \code-
115 QFileSelector selector;-
116 QFile defaultsFile(selector.select("data/defaults.conf"));-
117 \endcode-
118-
119 The files to be selected are placed in directories named with a \c'+' and a selector name. In the above-
120 example you could have the platform configurations selected by placing them in the following locations:-
121 \code-
122 data/defaults.conf-
123 data/+android/defaults.conf-
124 data/+ios/+en_GB/defaults.conf-
125 \endcode-
126-
127 To find selected files, QFileSelector looks in the same directory as the base file. If there are-
128 any directories of the form +<selector> with an active selector, QFileSelector will prefer a file-
129 with the same file name from that directory over the base file. These directories can be nested to-
130 check against multiple selectors, for example:-
131 \code-
132 images/background.png-
133 images/+android/+en_GB/background.png-
134 \endcode-
135 With those files available, you would select a different file on the android platform,-
136 but only if the locale was en_GB.-
137-
138 QFileSelector will not attempt to select if the base file does not exist. For error handling in-
139 the case no valid selectors are present, it is recommended to have a default or error-handling-
140 file in the base file location even if you expect selectors to be present for all deployments.-
141-
142 In a future version, some may be marked as deploy-time static and be moved during the-
143 deployment step as an optimization. As selectors come with a performance cost, it is-
144 recommended to avoid their use in circumstances involving performance-critical code.-
145-
146 \section1 Adding Selectors-
147-
148 Selectors normally available are-
149 \list-
150 \li platform, any of the following strings which match the platform the application is running-
151 on (list not exhaustive): android, ios, osx, darwin, mac, linux, wince, unix, windows.-
152 On Linux, if it can be determined, the name of the distribution too, like debian,-
153 fedora or opensuse.-
154 \li locale, same as QLocale().name().-
155 \endlist-
156-
157 Further selectors will be added from the \c QT_FILE_SELECTORS environment variable, which-
158 when set should be a set of comma separated selectors. Note that this variable will only be-
159 read once; selectors may not update if the variable changes while the application is running.-
160 The initial set of selectors are evaluated only once, on first use.-
161-
162 You can also add extra selectors at runtime for custom behavior. These will be used in any-
163 future calls to select(). If the extra selectors list has been changed, calls to select() will-
164 use the new list and may return differently.-
165-
166 \section1 Conflict Resolution when Multiple Selectors Apply-
167-
168 When multiple selectors could be applied to the same file, the first matching selector is chosen.-
169 The order selectors are checked in are:-
170-
171 \list 1-
172 \li Selectors set via setExtraSelectors(), in the order they are in the list-
173 \li Selectors in the \c QT_FILE_SELECTORS environment variable, from left to right-
174 \li Locale-
175 \li Platform-
176 \endlist-
177-
178 Here is an example involving multiple selectors matching at the same time. It uses platform-
179 selectors, plus an extra selector named "admin" is set by the application based on user-
180 credentials. The example is sorted so that the lowest matching file would be chosen if all-
181 selectors were present:-
182-
183 \code-
184 images/background.png-
185 images/+linux/background.png-
186 images/+windows/background.png-
187 images/+admin/background.png-
188 images/+admin/+linux/background.png-
189 \endcode-
190-
191 Because extra selectors are checked before platform the \c{+admin/background.png} will be chosen-
192 on Windows when the admin selector is set, and \c{+windows/background.png} will be chosen on-
193 Windows when the admin selector is not set. On Linux, the \c{+admin/+linux/background.png} will be-
194 chosen when admin is set, and the \c{+linux/background.png} when it is not.-
195-
196*/-
197-
198/*!-
199 Create a QFileSelector instance. This instance will have the same static selectors as other-
200 QFileSelector instances, but its own set of extra selectors.-
201-
202 If supplied, it will have the given QObject \a parent.-
203*/-
204QFileSelector::QFileSelector(QObject *parent)-
205 : QObject(*(new QFileSelectorPrivate()), parent)-
206{-
207}
executed 19 times by 1 test: end of block
Executed by:
  • tst_QFileSelector
19
208-
209/*!-
210 Destroys this selector instance.-
211*/-
212QFileSelector::~QFileSelector()-
213{-
214}-
215-
216/*!-
217 This function returns the selected version of the path, based on the conditions at runtime.-
218 If no selectable files are present, returns the original \a filePath.-
219-
220 If the original file does not exist, the original \a filePath is returned. This means that you-
221 must have a base file to fall back on, you cannot have only files in selectable sub-directories.-
222-
223 See the class overview for the selection algorithm.-
224*/-
225QString QFileSelector::select(const QString &filePath) const-
226{-
227 Q_D(const QFileSelector);-
228 return d->select(filePath);
executed 17 times by 1 test: return d->select(filePath);
Executed by:
  • tst_QFileSelector
17
229}-
230-
231static bool isLocalScheme(const QString &file)-
232{-
233 bool local = file == QLatin1String("qrc");-
234#ifdef Q_OS_ANDROID-
235 local |= file == QLatin1String("assets");-
236#endif-
237 return local;
executed 10 times by 1 test: return local;
Executed by:
  • tst_QFileSelector
10
238}-
239-
240/*!-
241 This is a convenience version of select operating on QUrl objects. If the scheme is not file or qrc,-
242 \a filePath is returned immediately. Otherwise selection is applied to the path of \a filePath-
243 and a QUrl is returned with the selected path and other QUrl parts the same as \a filePath.-
244-
245 See the class overview for the selection algorithm.-
246*/-
247QUrl QFileSelector::select(const QUrl &filePath) const-
248{-
249 Q_D(const QFileSelector);-
250 if (!isLocalScheme(filePath.scheme()) && !filePath.isLocalFile())
!isLocalScheme...Path.scheme())Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_QFileSelector
!filePath.isLocalFile()Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_QFileSelector
2-4
251 return filePath;
executed 2 times by 1 test: return filePath;
Executed by:
  • tst_QFileSelector
2
252 QUrl ret(filePath);-
253 if (isLocalScheme(filePath.scheme())) {
isLocalScheme(...Path.scheme())Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_QFileSelector
2
254 QLatin1String scheme(":");-
255#ifdef Q_OS_ANDROID-
256 // use other scheme because ":" means "qrc" here-
257 if (filePath.scheme() == QLatin1String("assets"))-
258 scheme = QLatin1String("assets:");-
259#endif-
260-
261 QString equivalentPath = scheme + filePath.path();-
262 QString selectedPath = d->select(equivalentPath);-
263 ret.setPath(selectedPath.remove(0, scheme.size()));-
264 } else {
executed 2 times by 1 test: end of block
Executed by:
  • tst_QFileSelector
2
265 ret = QUrl::fromLocalFile(d->select(ret.toLocalFile()));-
266 }
executed 2 times by 1 test: end of block
Executed by:
  • tst_QFileSelector
2
267 return ret;
executed 4 times by 1 test: return ret;
Executed by:
  • tst_QFileSelector
4
268}-
269-
270static QString selectionHelper(const QString &path, const QString &fileName, const QStringList &selectors)-
271{-
272 /* selectionHelper does a depth-first search of possible selected files. Because there is strict-
273 selector ordering in the API, we can stop checking as soon as we find the file in a directory-
274 which does not contain any other valid selector directories.-
275 */-
276 Q_ASSERT(path.isEmpty() || path.endsWith(QLatin1Char('/')));-
277-
278 for (const QString &s : selectors) {-
279 QString prospectiveBase = path + QLatin1Char(selectorIndicator) + s + QLatin1Char('/');-
280 QStringList remainingSelectors = selectors;-
281 remainingSelectors.removeAll(s);-
282 if (!QDir(prospectiveBase).exists())
!QDir(prospect...Base).exists()Description
TRUEevaluated 95 times by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEevaluated 23 times by 1 test
Evaluated by:
  • tst_QFileSelector
23-95
283 continue;
executed 95 times by 1 test: continue;
Executed by:
  • tst_QFileSelector
95
284 QString prospectiveFile = selectionHelper(prospectiveBase, fileName, remainingSelectors);-
285 if (!prospectiveFile.isEmpty())
!prospectiveFile.isEmpty()Description
TRUEevaluated 19 times by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_QFileSelector
4-19
286 return prospectiveFile;
executed 19 times by 1 test: return prospectiveFile;
Executed by:
  • tst_QFileSelector
19
287 }
executed 4 times by 1 test: end of block
Executed by:
  • tst_QFileSelector
4
288-
289 // If we reach here there were no successful files found at a lower level in this branch, so we-
290 // should check this level as a potential result.-
291 if (!QFile::exists(path + fileName))
!QFile::exists...th + fileName)Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEevaluated 20 times by 1 test
Evaluated by:
  • tst_QFileSelector
4-20
292 return QString();
executed 4 times by 1 test: return QString();
Executed by:
  • tst_QFileSelector
4
293 return path + fileName;
executed 20 times by 1 test: return path + fileName;
Executed by:
  • tst_QFileSelector
20
294}-
295-
296QString QFileSelectorPrivate::select(const QString &filePath) const-
297{-
298 Q_Q(const QFileSelector);-
299 QFileInfo fi(filePath);-
300 // If file doesn't exist, don't select-
301 if (!fi.exists())
!fi.exists()Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEevaluated 20 times by 1 test
Evaluated by:
  • tst_QFileSelector
1-20
302 return filePath;
executed 1 time by 1 test: return filePath;
Executed by:
  • tst_QFileSelector
1
303-
304 QString ret = selectionHelper(fi.path().isEmpty() ? QString() : fi.path() + QLatin1Char('/'),-
305 fi.fileName(), q->allSelectors());-
306-
307 if (!ret.isEmpty())
!ret.isEmpty()Description
TRUEevaluated 20 times by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEnever evaluated
0-20
308 return ret;
executed 20 times by 1 test: return ret;
Executed by:
  • tst_QFileSelector
20
309 return filePath;
never executed: return filePath;
0
310}-
311-
312/*!-
313 Returns the list of extra selectors which have been added programmatically to this instance.-
314*/-
315QStringList QFileSelector::extraSelectors() const-
316{-
317 Q_D(const QFileSelector);-
318 return d->extras;
never executed: return d->extras;
0
319}-
320-
321/*!-
322 Sets the \a list of extra selectors which have been added programmatically to this instance.-
323-
324 These selectors have priority over any which have been automatically picked up.-
325*/-
326void QFileSelector::setExtraSelectors(const QStringList &list)-
327{-
328 Q_D(QFileSelector);-
329 d->extras = list;-
330}
executed 18 times by 1 test: end of block
Executed by:
  • tst_QFileSelector
18
331-
332/*!-
333 Returns the complete, ordered list of selectors used by this instance-
334*/-
335QStringList QFileSelector::allSelectors() const-
336{-
337 Q_D(const QFileSelector);-
338 QMutexLocker locker(&sharedDataMutex);-
339 QFileSelectorPrivate::updateSelectors();-
340 return d->extras + sharedData->staticSelectors;
executed 20 times by 1 test: return d->extras + sharedData->staticSelectors;
Executed by:
  • tst_QFileSelector
20
341}-
342-
343void QFileSelectorPrivate::updateSelectors()-
344{-
345 if (!sharedData->staticSelectors.isEmpty())
!sharedData->s...tors.isEmpty()Description
TRUEevaluated 18 times by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_QFileSelector
2-18
346 return; //Already loaded
executed 18 times by 1 test: return;
Executed by:
  • tst_QFileSelector
18
347-
348 QLatin1Char pathSep(',');-
349 QStringList envSelectors = QString::fromLatin1(qgetenv("QT_FILE_SELECTORS"))-
350 .split(pathSep, QString::SkipEmptyParts);-
351 if (envSelectors.count())
envSelectors.count()Description
TRUEnever evaluated
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_QFileSelector
0-2
352 sharedData->staticSelectors << envSelectors;
never executed: sharedData->staticSelectors << envSelectors;
0
353-
354 if (!qEnvironmentVariableIsEmpty(env_override))
!qEnvironmentV...(env_override)Description
TRUEnever evaluated
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_QFileSelector
0-2
355 return;
never executed: return;
0
356-
357 sharedData->staticSelectors << sharedData->preloadedStatics; //Potential for static selectors from other modules-
358-
359 // TODO: Update on locale changed?-
360 sharedData->staticSelectors << QLocale().name();-
361-
362 sharedData->staticSelectors << platformSelectors();-
363}
executed 2 times by 1 test: end of block
Executed by:
  • tst_QFileSelector
2
364-
365QStringList QFileSelectorPrivate::platformSelectors()-
366{-
367 // similar, but not identical to QSysInfo::osType-
368 QStringList ret;-
369#if defined(Q_OS_WIN)-
370 // can't fall back to QSysInfo because we need both "winphone" and "winrt" for the Windows Phone case-
371 ret << QStringLiteral("windows");-
372 ret << QSysInfo::kernelType(); // "wince" and "winnt"-
373# if defined(Q_OS_WINRT)-
374 ret << QStringLiteral("winrt");-
375# if defined(Q_OS_WINPHONE)-
376 ret << QStringLiteral("winphone");-
377# endif-
378# endif-
379#elif defined(Q_OS_UNIX)-
380 ret << QStringLiteral("unix");
executed 3 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_QFileSelector
3
381# if !defined(Q_OS_ANDROID)-
382 // we don't want "linux" for Android-
383 ret << QSysInfo::kernelType();-
384# ifdef Q_OS_MAC-
385 ret << QStringLiteral("mac"); // compatibility, since kernelType() is "darwin"-
386# endif-
387# endif-
388 QString productName = QSysInfo::productType();-
389# ifdef Q_OS_MACOS-
390 if (productName != QLatin1String("osx"))-
391 ret << QStringLiteral("osx"); // compatibility-
392# endif-
393 if (productName != QLatin1String("unknown"))
productName !=...ing("unknown")Description
TRUEevaluated 3 times by 1 test
Evaluated by:
  • tst_QFileSelector
FALSEnever evaluated
0-3
394 ret << productName; // "opensuse", "fedora", "macos", "ios", "android"
executed 3 times by 1 test: ret << productName;
Executed by:
  • tst_QFileSelector
3
395#endif-
396 return ret;
executed 3 times by 1 test: return ret;
Executed by:
  • tst_QFileSelector
3
397}-
398-
399void QFileSelectorPrivate::addStatics(const QStringList &statics)-
400{-
401 QMutexLocker locker(&sharedDataMutex);-
402 sharedData->preloadedStatics << statics;-
403 sharedData->staticSelectors.clear();-
404}
executed 1 time by 1 test: end of block
Executed by:
  • tst_QFileSelector
1
405-
406QT_END_NAMESPACE-
407-
408#include "moc_qfileselector.cpp"-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9