1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
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 http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include <QtTest/qtest.h>
38#include "../shared/visualtestutil.h"
39
40#include <QtGui/qpalette.h>
41#include <QtGui/private/qguiapplication_p.h>
42#include <QtQml/qqmlengine.h>
43#include <QtQml/qqmlcomponent.h>
44#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
45#include <QtQuickTemplates2/private/qquickcontrol_p.h>
46#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
47#include <QtQuickTemplates2/private/qquickpopup_p.h>
48#include <QtQuickTemplates2/private/qquicktheme_p_p.h>
49
50using namespace QQuickVisualTestUtil;
51
52class tst_palette : public QQmlDataTest
53{
54 Q_OBJECT
55
56private slots:
57 void initTestCase();
58
59 void palette_data();
60 void palette();
61
62 void inheritance_data();
63 void inheritance();
64
65 void defaultPalette_data();
66 void defaultPalette();
67
68 void listView_data();
69 void listView();
70};
71
72void tst_palette::initTestCase()
73{
74 QQmlDataTest::initTestCase();
75
76 // Import QtQuick.Controls to initialize styles and themes so that
77 // QQuickControlPrivate::themePalette() returns a palette from the
78 // style's theme instead of the platform's theme.
79 QQmlEngine engine;
80 QQmlComponent component(&engine);
81 component.setData("import QtQuick.Controls 2.3; Control { }", baseUrl: QUrl());
82 delete component.create();
83}
84
85void tst_palette::palette_data()
86{
87 QTest::addColumn<QString>(name: "testFile");
88 QTest::addColumn<QPalette>(name: "expectedPalette");
89
90 QPalette defaultPalette = QQuickTheme::palette(scope: QQuickTheme::System);
91 defaultPalette.setColor(acr: QPalette::Base, acolor: QColor("#efefef"));
92 defaultPalette.setColor(acr: QPalette::Text, acolor: QColor("#101010"));
93
94 QTest::newRow(dataTag: "Control") << "palette-control-default.qml" << defaultPalette;
95 QTest::newRow(dataTag: "AppWindow") << "palette-appwindow-default.qml" << defaultPalette;
96 QTest::newRow(dataTag: "Popup") << "palette-popup-default.qml" << defaultPalette;
97
98 QPalette customPalette;
99 customPalette.setColor(acr: QPalette::AlternateBase, acolor: QColor("aqua"));
100 customPalette.setColor(acr: QPalette::Base, acolor: QColor("azure"));
101 customPalette.setColor(acr: QPalette::BrightText, acolor: QColor("beige"));
102 customPalette.setColor(acr: QPalette::Button, acolor: QColor("bisque"));
103 customPalette.setColor(acr: QPalette::ButtonText, acolor: QColor("chocolate"));
104 customPalette.setColor(acr: QPalette::Dark, acolor: QColor("coral"));
105 customPalette.setColor(acr: QPalette::Highlight, acolor: QColor("crimson"));
106 customPalette.setColor(acr: QPalette::HighlightedText, acolor: QColor("fuchsia"));
107 customPalette.setColor(acr: QPalette::Light, acolor: QColor("gold"));
108 customPalette.setColor(acr: QPalette::Link, acolor: QColor("indigo"));
109 customPalette.setColor(acr: QPalette::LinkVisited, acolor: QColor("ivory"));
110 customPalette.setColor(acr: QPalette::Mid, acolor: QColor("khaki"));
111 customPalette.setColor(acr: QPalette::Midlight, acolor: QColor("lavender"));
112 customPalette.setColor(acr: QPalette::Shadow, acolor: QColor("linen"));
113 customPalette.setColor(acr: QPalette::Text, acolor: QColor("moccasin"));
114 customPalette.setColor(acr: QPalette::ToolTipBase, acolor: QColor("navy"));
115 customPalette.setColor(acr: QPalette::ToolTipText, acolor: QColor("orchid"));
116 customPalette.setColor(acr: QPalette::Window, acolor: QColor("plum"));
117 customPalette.setColor(acr: QPalette::WindowText, acolor: QColor("salmon"));
118
119 QTest::newRow(dataTag: "Control:custom") << "palette-control-custom.qml" << customPalette;
120 QTest::newRow(dataTag: "AppWindow:custom") << "palette-appwindow-custom.qml" << customPalette;
121 QTest::newRow(dataTag: "Popup:custom") << "palette-popup-custom.qml" << customPalette;
122}
123
124void tst_palette::palette()
125{
126 QFETCH(QString, testFile);
127 QFETCH(QPalette, expectedPalette);
128
129 QQmlEngine engine;
130 QQmlComponent component(&engine);
131 component.loadUrl(url: testFileUrl(fileName: testFile));
132
133 QScopedPointer<QObject> object(component.create());
134 QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
135
136 QVariant var = object->property(name: "palette");
137 QVERIFY(var.isValid());
138
139 QPalette actualPalette = var.value<QPalette>();
140 QCOMPARE(actualPalette, expectedPalette);
141}
142
143void tst_palette::inheritance_data()
144{
145 QTest::addColumn<QString>(name: "testFile");
146
147 QTest::newRow(dataTag: "Control") << "inheritance-control.qml";
148 QTest::newRow(dataTag: "Child Control") << "inheritance-childcontrol.qml";
149 QTest::newRow(dataTag: "Dynamic Control") << "inheritance-dynamiccontrol.qml";
150 QTest::newRow(dataTag: "Dynamic Child Control") << "inheritance-dynamicchildcontrol.qml";
151
152 QTest::newRow(dataTag: "Popup") << "inheritance-popup.qml";
153 QTest::newRow(dataTag: "Child Popup") << "inheritance-childpopup.qml";
154 QTest::newRow(dataTag: "Dynamic Popup") << "inheritance-dynamicpopup.qml";
155 QTest::newRow(dataTag: "Dynamic Child Popup") << "inheritance-dynamicchildpopup.qml";
156}
157
158void tst_palette::inheritance()
159{
160 QFETCH(QString, testFile);
161
162 QQmlEngine engine;
163 QQmlComponent component(&engine);
164 component.loadUrl(url: testFileUrl(fileName: testFile));
165
166 QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(object: component.create()));
167 QVERIFY2(!window.isNull(), qPrintable(component.errorString()));
168
169 QObject *control = window->property(name: "control").value<QObject *>();
170 QObject *child = window->property(name: "child").value<QObject *>();
171 QObject *grandChild = window->property(name: "grandChild").value<QObject *>();
172 QVERIFY(control && child && grandChild);
173
174 QPalette defaultPalette = QQuickTheme::palette(scope: QQuickTheme::System);
175 defaultPalette.setColor(acr: QPalette::Base, acolor: QColor("#efefef"));
176 defaultPalette.setColor(acr: QPalette::Text, acolor: QColor("#101010"));
177
178 QCOMPARE(window->palette(), defaultPalette);
179
180 QCOMPARE(control->property("palette").value<QPalette>(), defaultPalette);
181 QCOMPARE(child->property("palette").value<QPalette>(), defaultPalette);
182 QCOMPARE(grandChild->property("palette").value<QPalette>(), defaultPalette);
183
184 QPalette childPalette(defaultPalette);
185 childPalette.setColor(acr: QPalette::Base, acolor: Qt::red);
186 childPalette.setColor(acr: QPalette::Text, acolor: Qt::green);
187 childPalette.setColor(acr: QPalette::Button, acolor: Qt::blue);
188 child->setProperty(name: "palette", value: childPalette);
189 QCOMPARE(child->property("palette").value<QPalette>(), childPalette);
190 QCOMPARE(grandChild->property("palette").value<QPalette>(), childPalette);
191
192 QPalette grandChildPalette(childPalette);
193 grandChildPalette.setColor(acr: QPalette::Base, acolor: Qt::cyan);
194 grandChildPalette.setColor(acr: QPalette::Mid, acolor: Qt::magenta);
195 grandChild->setProperty(name: "palette", value: grandChildPalette);
196 QCOMPARE(child->property("palette").value<QPalette>(), childPalette);
197 QCOMPARE(grandChild->property("palette").value<QPalette>(), grandChildPalette);
198
199 QPalette windowPalette(defaultPalette);
200 windowPalette.setColor(acr: QPalette::Window, acolor: Qt::gray);
201 window->setPalette(windowPalette);
202 QCOMPARE(window->palette(), windowPalette);
203 QCOMPARE(control->property("palette").value<QPalette>(), windowPalette);
204
205 childPalette.setColor(acr: QPalette::Window, acolor: Qt::gray);
206 QCOMPARE(child->property("palette").value<QPalette>(), childPalette);
207
208 grandChildPalette.setColor(acr: QPalette::Window, acolor: Qt::gray);
209 QCOMPARE(grandChild->property("palette").value<QPalette>(), grandChildPalette);
210
211 child->setProperty(name: "palette", value: QVariant());
212 QCOMPARE(child->property("palette").value<QPalette>(), windowPalette);
213 QCOMPARE(grandChild->property("palette").value<QPalette>(), grandChildPalette);
214
215 grandChild->setProperty(name: "palette", value: QVariant());
216 QCOMPARE(grandChild->property("palette").value<QPalette>(), windowPalette);
217}
218
219class TestTheme : public QQuickTheme
220{
221public:
222 static const int NPalettes = QQuickTheme::Tumbler + 1;
223
224 TestTheme()
225 {
226 for (int i = 0; i < NPalettes; ++i)
227 setPalette(scope: static_cast<Scope>(i), palette: QPalette(QColor::fromRgb(rgb: i)));
228 }
229};
230
231Q_DECLARE_METATYPE(QQuickTheme::Scope)
232
233void tst_palette::defaultPalette_data()
234{
235 QTest::addColumn<QString>(name: "control");
236 QTest::addColumn<QQuickTheme::Scope>(name: "scope");
237
238 QTest::newRow(dataTag: "AbstractButton") << "AbstractButton" << QQuickTheme::System;
239 QTest::newRow(dataTag: "ApplicationWindow") << "ApplicationWindow" << QQuickTheme::System;
240 QTest::newRow(dataTag: "Button") << "Button" << QQuickTheme::Button;
241 QTest::newRow(dataTag: "CheckBox") << "CheckBox" << QQuickTheme::CheckBox;
242 QTest::newRow(dataTag: "CheckDelegate") << "CheckDelegate" << QQuickTheme::ListView;
243 QTest::newRow(dataTag: "ComboBox") << "ComboBox" << QQuickTheme::ComboBox;
244 QTest::newRow(dataTag: "Container") << "Container" << QQuickTheme::System;
245 QTest::newRow(dataTag: "Control") << "Control" << QQuickTheme::System;
246 QTest::newRow(dataTag: "Dial") << "Dial" << QQuickTheme::System;
247 QTest::newRow(dataTag: "Dialog") << "Dialog" << QQuickTheme::System;
248 QTest::newRow(dataTag: "DialogButtonBox") << "DialogButtonBox" << QQuickTheme::System;
249 QTest::newRow(dataTag: "Drawer") << "Drawer" << QQuickTheme::System;
250 QTest::newRow(dataTag: "Frame") << "Frame" << QQuickTheme::System;
251 QTest::newRow(dataTag: "GroupBox") << "GroupBox" << QQuickTheme::GroupBox;
252 QTest::newRow(dataTag: "ItemDelegate") << "ItemDelegate" << QQuickTheme::ItemView;
253 QTest::newRow(dataTag: "Label") << "Label" << QQuickTheme::Label;
254 QTest::newRow(dataTag: "Menu") << "Menu" << QQuickTheme::Menu;
255 QTest::newRow(dataTag: "MenuItem") << "MenuItem" << QQuickTheme::Menu;
256 QTest::newRow(dataTag: "MenuSeparator") << "MenuSeparator" << QQuickTheme::Menu;
257 QTest::newRow(dataTag: "Page") << "Page" << QQuickTheme::System;
258 QTest::newRow(dataTag: "Pane") << "Pane" << QQuickTheme::System;
259 QTest::newRow(dataTag: "Popup") << "Popup" << QQuickTheme::System;
260 QTest::newRow(dataTag: "ProgressBar") << "ProgressBar" << QQuickTheme::System;
261 QTest::newRow(dataTag: "RadioButton") << "RadioButton" << QQuickTheme::RadioButton;
262 QTest::newRow(dataTag: "RadioDelegate") << "RadioDelegate" << QQuickTheme::ListView;
263 QTest::newRow(dataTag: "RangeSlider") << "RangeSlider" << QQuickTheme::System;
264 QTest::newRow(dataTag: "RoundButton") << "RoundButton" << QQuickTheme::Button;
265 QTest::newRow(dataTag: "ScrollBar") << "ScrollBar" << QQuickTheme::System;
266 QTest::newRow(dataTag: "ScrollIndicator") << "ScrollIndicator" << QQuickTheme::System;
267 QTest::newRow(dataTag: "Slider") << "Slider" << QQuickTheme::System;
268 QTest::newRow(dataTag: "SpinBox") << "SpinBox" << QQuickTheme::SpinBox;
269 QTest::newRow(dataTag: "SwipeDelegate") << "SwipeDelegate" << QQuickTheme::ListView;
270 QTest::newRow(dataTag: "Switch") << "Switch" << QQuickTheme::Switch;
271 QTest::newRow(dataTag: "SwitchDelegate") << "SwitchDelegate" << QQuickTheme::ListView;
272 QTest::newRow(dataTag: "TabBar") << "TabBar" << QQuickTheme::TabBar;
273 QTest::newRow(dataTag: "TabButton") << "TabButton" << QQuickTheme::TabBar;
274 QTest::newRow(dataTag: "TextArea") << "TextArea" << QQuickTheme::TextArea;
275 QTest::newRow(dataTag: "TextField") << "TextField" << QQuickTheme::TextField;
276 QTest::newRow(dataTag: "ToolBar") << "ToolBar" << QQuickTheme::ToolBar;
277 QTest::newRow(dataTag: "ToolButton") << "ToolButton" << QQuickTheme::ToolBar;
278 QTest::newRow(dataTag: "ToolSeparator") << "ToolSeparator" << QQuickTheme::ToolBar;
279 QTest::newRow(dataTag: "ToolTip") << "ToolTip" << QQuickTheme::ToolTip;
280 QTest::newRow(dataTag: "Tumbler") << "Tumbler" << QQuickTheme::Tumbler;
281}
282
283void tst_palette::defaultPalette()
284{
285 QFETCH(QString, control);
286 QFETCH(QQuickTheme::Scope, scope);
287
288 QQmlEngine engine;
289 QQmlComponent component(&engine);
290 component.setData(QString("import QtQuick.Controls 2.3; %1 { }").arg(a: control).toUtf8(), baseUrl: QUrl());
291
292 // The call to setData() above causes QQuickDefaultTheme to be set as the current theme,
293 // so we must make sure we only set our theme afterwards.
294 QQuickThemePrivate::instance.reset(other: new TestTheme);
295
296 QScopedPointer<QObject> object(component.create());
297 QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
298
299 QVariant var = object->property(name: "palette");
300 QVERIFY(var.isValid());
301
302 QPalette expectedPalette = QQuickTheme::palette(scope);
303 QPalette actualPalette = var.value<QPalette>();
304 QCOMPARE(actualPalette, expectedPalette);
305}
306
307void tst_palette::listView_data()
308{
309 QTest::addColumn<QString>(name: "objectName");
310
311 QTest::newRow(dataTag: "Control") << "control";
312 QTest::newRow(dataTag: "Label") << "label";
313 QTest::newRow(dataTag: "TextArea") << "textarea";
314 QTest::newRow(dataTag: "TextField") << "textfield";
315}
316
317void tst_palette::listView()
318{
319 QFETCH(QString, objectName);
320
321 QQmlEngine engine;
322 QQmlComponent component(&engine);
323 component.loadUrl(url: testFileUrl(fileName: "listview.qml"));
324
325 QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(object: component.create()));
326 QVERIFY2(!window.isNull(), qPrintable(component.errorString()));
327
328 window->show();
329 QVERIFY(QTest::qWaitForWindowActive(window.data()));
330
331 QQuickItem *listView = window->property(name: "listView").value<QQuickItem *>();
332 QVERIFY(listView);
333
334 QQuickItem *contentItem = listView->property(name: "contentItem").value<QQuickItem *>();
335 QVERIFY(contentItem);
336
337 QVERIFY(QMetaObject::invokeMethod(listView, "forceLayout"));
338
339 QQuickItem *column = contentItem->childItems().value(i: 0);
340 QVERIFY(column);
341
342 QQuickItem *control = column->property(name: objectName.toUtf8()).value<QQuickItem *>();
343 QVERIFY(control);
344
345 QCOMPARE(control->property("palette").value<QPalette>().color(QPalette::Highlight), QColor(Qt::red));
346}
347
348QTEST_MAIN(tst_palette)
349
350#include "tst_palette.moc"
351

source code of qtquickcontrols2/tests/auto/palette/tst_palette.cpp