aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrols2/qquickstyleselector.cpp
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@theqtcompany.com>2016-04-13 17:26:45 +0200
committerJ-P Nurmi <jpnurmi@theqtcompany.com>2016-04-13 18:18:24 +0000
commit4bc65664627c6359c45754fb89022e00d616441b (patch)
tree8c7407e146c69daa3045833ad4e131e5e31e818a /src/quickcontrols2/qquickstyleselector.cpp
parent9cc38f6d17643978b5f65829c08c105a7783ac10 (diff)
Controls: rename the C++ module to qtquickcontrols2
Change-Id: I087a39baebc296a340739161874636926adaa56c Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
Diffstat (limited to 'src/quickcontrols2/qquickstyleselector.cpp')
-rw-r--r--src/quickcontrols2/qquickstyleselector.cpp193
1 files changed, 193 insertions, 0 deletions
diff --git a/src/quickcontrols2/qquickstyleselector.cpp b/src/quickcontrols2/qquickstyleselector.cpp
new file mode 100644
index 00000000..64e9d500
--- /dev/null
+++ b/src/quickcontrols2/qquickstyleselector.cpp
@@ -0,0 +1,193 @@
+/***************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Labs Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickstyleselector_p.h"
+#include "qquickstyleselector_p_p.h"
+#include "qquickstyle.h"
+
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qsysinfo.h>
+#include <QtCore/qlocale.h>
+
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static bool isLocalScheme(const QString &scheme)
+{
+ bool local = scheme == QLatin1String("qrc");
+#ifdef Q_OS_ANDROID
+ local |= scheme == QLatin1String("assets");
+#endif
+ return local;
+}
+
+// similar, but not identical to QSysInfo::osType
+static QStringList platformSelectors()
+{
+ static QStringList selectors;
+ if (!selectors.isEmpty())
+ return selectors;
+
+#if defined(Q_OS_WIN)
+ // can't fall back to QSysInfo because we need both "winphone" and "winrt" for the Windows Phone case
+ selectors << QStringLiteral("windows");
+ selectors << QSysInfo::kernelType(); // "wince" and "winnt"
+# if defined(Q_OS_WINRT)
+ selectors << QStringLiteral("winrt");
+# if defined(Q_OS_WINPHONE)
+ selectors << QStringLiteral("winphone");
+# endif
+# endif
+#elif defined(Q_OS_UNIX)
+ selectors << QStringLiteral("unix");
+# if !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY)
+ // we don't want "linux" for Android or "qnx" for Blackberry here
+ selectors << QSysInfo::kernelType();
+# ifdef Q_OS_MAC
+ selectors << QStringLiteral("mac"); // compatibility, since kernelType() is "darwin"
+# endif
+# endif
+ QString productName = QSysInfo::productType();
+ if (productName != QLatin1String("unknown"))
+ selectors << productName; // "opensuse", "fedora", "osx", "ios", "blackberry", "android"
+#endif
+ return selectors;
+}
+
+static QStringList allSelectors(bool includeStyle)
+{
+ QStringList selectors = platformSelectors();
+ selectors += QLocale().name();
+ if (includeStyle) {
+ QString style = QQuickStyle::name();
+ if (!style.isEmpty())
+ selectors.prepend(style.toLower());
+ }
+ return selectors;
+}
+
+static QString selectionHelper(const QString &path, const QString &fileName, const QStringList &selectors)
+{
+ /* selectionHelper does a depth-first search of possible selected files. Because there is strict
+ selector ordering in the API, we can stop checking as soon as we find the file in a directory
+ which does not contain any other valid selector directories.
+ */
+ Q_ASSERT(path.isEmpty() || path.endsWith(QLatin1Char('/')));
+
+ for (const QString &s : selectors) {
+ QString prospectiveBase = path + s + QLatin1Char('/');
+ QStringList remainingSelectors = selectors;
+ remainingSelectors.removeAll(s);
+ if (!QDir(prospectiveBase).exists())
+ continue;
+ QString prospectiveFile = selectionHelper(prospectiveBase, fileName, remainingSelectors);
+ if (!prospectiveFile.isEmpty())
+ return prospectiveFile;
+ }
+
+ // If we reach here there were no successful files found at a lower level in this branch, so we
+ // should check this level as a potential result.
+ const QString result = path + fileName;
+ if (!QFileInfo::exists(result))
+ return QString();
+ return result;
+}
+
+QString QQuickStyleSelectorPrivate::select(const QString &filePath) const
+{
+ QFileInfo fi(filePath);
+ // If file doesn't exist, don't select
+ if (!fi.exists())
+ return filePath;
+
+ const QString path = fi.path();
+ const QString ret = selectionHelper(path.isEmpty() ? QString() : path + QLatin1Char('/'),
+ fi.fileName(), allSelectors(true));
+
+ if (!ret.isEmpty())
+ return ret;
+ return filePath;
+}
+
+QQuickStyleSelector::QQuickStyleSelector() : d_ptr(new QQuickStyleSelectorPrivate)
+{
+}
+
+QQuickStyleSelector::~QQuickStyleSelector()
+{
+}
+
+QUrl QQuickStyleSelector::baseUrl() const
+{
+ Q_D(const QQuickStyleSelector);
+ return d->baseUrl;
+}
+
+void QQuickStyleSelector::setBaseUrl(const QUrl &url)
+{
+ Q_D(QQuickStyleSelector);
+ d->baseUrl = url;
+}
+
+QString QQuickStyleSelector::select(const QString &fileName) const
+{
+ Q_D(const QQuickStyleSelector);
+ const QString overridePath = QQuickStyle::path();
+ if (!overridePath.isEmpty()) {
+ const QString stylePath = overridePath + QQuickStyle::name() + QLatin1Char('/');
+ if (QFile::exists(stylePath + fileName)) {
+ // the style name is included to the path, so exclude it from the selectors.
+ // the rest of the selectors (os, locale) are still valid, though.
+ const QString selectedPath = selectionHelper(stylePath, fileName, allSelectors(false));
+ if (selectedPath.startsWith(QLatin1Char(':')))
+ return QLatin1String("qrc") + selectedPath;
+ return QUrl::fromLocalFile(selectedPath).toString();
+ }
+ }
+
+ QUrl url(d->baseUrl.toString() + QLatin1Char('/') + fileName);
+ if (isLocalScheme(url.scheme())) {
+ QString equivalentPath = QLatin1Char(':') + url.path();
+ QString selectedPath = d->select(equivalentPath);
+ url.setPath(selectedPath.remove(0, 1));
+ } else if (url.isLocalFile()) {
+ url = QUrl::fromLocalFile(d->select(url.toLocalFile()));
+ }
+ return url.toString();
+}
+
+QT_END_NAMESPACE