1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QTest>
30#include <QRegularExpression>
31#include <QQmlEngine>
32#include <QQmlComponent>
33#include <QQuickItem>
34#include <QQuickWindow>
35#include <QStringListModel>
36#include "../shared/util.h"
37
38class tst_customcontrolsstyle : public QQmlDataTest
39{
40 Q_OBJECT
41
42public:
43 tst_customcontrolsstyle() {}
44
45private slots:
46 void initTestCase();
47
48 void style_data();
49 void style();
50 void changeStyle();
51};
52
53void tst_customcontrolsstyle::initTestCase()
54{
55 QQmlDataTest::initTestCase();
56}
57
58void tst_customcontrolsstyle::style_data()
59{
60 QTest::addColumn<QString>(name: "specifiedStyle");
61 QTest::addColumn<QString>(name: "expectedStyleName");
62
63 QTest::newRow(dataTag: "NonExistentStyle") << QString::fromLatin1(str: "NonExistentStyle") << QString::fromLatin1(str: "Base");
64 QTest::newRow(dataTag: "CustomFileSystemStyle") << directory() + QString::fromLatin1(str: "/Style") << QString::fromLatin1(str: "Style");
65 QTest::newRow(dataTag: "BuiltinQrcStyle") << QString::fromLatin1(str: "ResourceStyle") << QString::fromLatin1(str: "ResourceStyle"); // from :/qt-project.org/imports/QtQuick/Controls/Styles
66 QTest::newRow(dataTag: "CustomQrcStyle") << QString::fromLatin1(str: ":/Style") << QString::fromLatin1(str: "Style");
67}
68
69void tst_customcontrolsstyle::style()
70{
71 if (QGuiApplication::platformName() == "offscreen")
72 QSKIP("Using grabImage does not work on offscreen platform");
73
74 QFETCH(QString, specifiedStyle);
75 QFETCH(QString, expectedStyleName);
76
77 qputenv(varName: "QT_QUICK_CONTROLS_1_STYLE", value: specifiedStyle.toLocal8Bit());
78
79 const bool expectBase = expectedStyleName == QLatin1String("Base");
80
81 if (specifiedStyle != expectedStyleName && expectBase) {
82 QString regexStr = QString::fromLatin1(str: "WARNING: Cannot find style \"%1\" - fallback: .*%2").arg(a: specifiedStyle).arg(a: "Base");
83 QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(regexStr));
84 }
85
86 QQmlEngine engine;
87
88 QQmlComponent component(&engine, testFileUrl(fileName: "TestComponent.qml"));
89 QTRY_COMPARE(component.status(), QQmlComponent::Ready);
90
91 QScopedPointer<QObject> object(component.create());
92 QVERIFY(object);
93
94 QCOMPARE(object->property("styleName").toString(), expectedStyleName);
95
96 QVariant returnedValue;
97 QMetaObject::invokeMethod(obj: object.data(), member: "buttonStyleComponent", Q_RETURN_ARG(QVariant, returnedValue));
98
99 QVERIFY(returnedValue.isValid());
100 QVERIFY(returnedValue.canConvert<QQmlComponent*>());
101 QVERIFY(returnedValue.value<QQmlComponent*>());
102
103 QQuickWindow *window = qobject_cast<QQuickWindow*>(object: object.data());
104 QVERIFY(QTest::qWaitForWindowExposed(window));
105
106 if (!expectBase) {
107 QImage windowImage = window->grabWindow();
108 QCOMPARE(windowImage.pixel(0, 0), QColor(Qt::red).rgb());
109 }
110}
111
112// start with Base, switch to custom style later on (for a specific QML engine)
113void tst_customcontrolsstyle::changeStyle()
114{
115 if (QGuiApplication::platformName() == "offscreen")
116 QSKIP("Using grabImage does not work on offscreen platform");
117
118 qputenv(varName: "QT_QUICK_CONTROLS_1_STYLE", value: "Base");
119 QByteArray importPath = qgetenv(varName: "QML2_IMPORT_PATH");
120 if (importPath.isEmpty())
121 importPath = QFile::encodeName(fileName: directory());
122 else
123 importPath.prepend(a: QFile::encodeName(fileName: directory()) + QDir::listSeparator().toLatin1());
124 qputenv(varName: "QML2_IMPORT_PATH", value: importPath);
125
126 QQmlEngine engine;
127
128 QQmlComponent component(&engine, testFileUrl(fileName: "TestComponent.qml"));
129 QTRY_COMPARE(component.status(), QQmlComponent::Ready);
130
131 QScopedPointer<QObject> object(component.create());
132 QVERIFY(object);
133
134 QCOMPARE(object->property("styleName").toString(), QString("Base"));
135
136 // Switch to "Style" custom style
137 QQmlComponent c(&engine);
138 c.setData("import QtQuick 2.1\n"
139 "import QtQuick.Controls 1.0\n"
140 "import QtQuick.Controls.Private 1.0\n"
141 "Item {"
142 "Component.onCompleted: {"
143 "Settings.styleName = \"Style\";"
144 "}"
145 "}", baseUrl: QUrl());
146 QObject *o = c.create();
147 o->deleteLater();
148
149 QCOMPARE(object->property("styleName").toString(), QString("Style"));
150 QMetaObject::invokeMethod(obj: object.data(), member: "buttonStyleComponent");
151 QQuickWindow *window = qobject_cast<QQuickWindow*>(object: object.data());
152 QVERIFY(QTest::qWaitForWindowExposed(window));
153 QImage windowImage = window->grabWindow();
154 QCOMPARE(windowImage.pixel(0, 0), QColor(Qt::blue).rgb());
155}
156
157QTEST_MAIN(tst_customcontrolsstyle)
158
159#include "tst_customcontrolsstyle.moc"
160

source code of qtquickcontrols/tests/auto/customcontrolsstyle/tst_customcontrolsstyle.cpp