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/qfont.h>
41#include <QtGui/qpa/qplatformtheme.h>
42#include <QtGui/private/qguiapplication_p.h>
43#include <QtQml/qqmlengine.h>
44#include <QtQml/qqmlcomponent.h>
45#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
46#include <QtQuickTemplates2/private/qquickcontrol_p.h>
47#include <QtQuickTemplates2/private/qquickpopup_p.h>
48#include <QtQuickTemplates2/private/qquicktheme_p_p.h>
49
50using namespace QQuickVisualTestUtil;
51
52class tst_font : public QQmlDataTest
53{
54 Q_OBJECT
55
56private slots:
57 void systemFont();
58
59 void font_data();
60 void font();
61
62 void inheritance_data();
63 void inheritance();
64
65 void defaultFont_data();
66 void defaultFont();
67
68 void listView_data();
69 void listView();
70};
71
72static QFont testFont()
73{
74 QQmlEngine engine;
75 QQmlComponent component(&engine);
76 component.setData("import QtQuick 2.0; import QtQuick.Controls 2.0; Text { }", baseUrl: QUrl());
77
78 QScopedPointer<QObject> object(component.create());
79 Q_ASSERT_X(!object.isNull(), "testFont", qPrintable(component.errorString()));
80
81 QVariant var = object->property(name: "font");
82 Q_ASSERT_X(var.isValid(), "testFont", var.typeName());
83 return var.value<QFont>();
84}
85
86void tst_font::systemFont()
87{
88 QSKIP("QTBUG-70063: qmlClearTypeRegistrations() call causes crash");
89
90 const QFont *originalSystemFont = QGuiApplicationPrivate::platformTheme()->font(type: QPlatformTheme::SystemFont);
91 if (!originalSystemFont)
92 QSKIP("Cannot test the system font on a minimal platform");
93
94 const QFont fontBefore = testFont();
95 QCOMPARE(fontBefore, *originalSystemFont);
96
97 qmlClearTypeRegistrations();
98 delete QGuiApplicationPrivate::app_font;
99 QGuiApplicationPrivate::app_font = nullptr;
100
101 const QFont appFont = QGuiApplication::font();
102 QCOMPARE(appFont, *originalSystemFont);
103
104 const QFont fontAfter = testFont();
105 QCOMPARE(fontAfter, *originalSystemFont);
106}
107
108void tst_font::font_data()
109{
110 QTest::addColumn<QString>(name: "testFile");
111 QTest::addColumn<QFont>(name: "expectedFont");
112
113 QTest::newRow(dataTag: "Control") << "font-control-default.qml" << QFont();
114 QTest::newRow(dataTag: "AppWindow") << "font-appwindow-default.qml" << QFont();
115 QTest::newRow(dataTag: "Popup") << "font-popup-default.qml" << QFont();
116
117 QFont customFont;
118 customFont.setCapitalization(QFont::AllUppercase);
119 customFont.setFamily("Courier");
120 customFont.setItalic(true);
121 customFont.setPixelSize(60);
122 customFont.setStrikeOut(true);
123 customFont.setUnderline(true);
124 customFont.setWeight(QFont::DemiBold);
125
126 QTest::newRow(dataTag: "Control:custom") << "font-control-custom.qml" << customFont;
127 QTest::newRow(dataTag: "AppWindow:custom") << "font-appwindow-custom.qml" << customFont;
128 QTest::newRow(dataTag: "Popup:custom") << "font-popup-custom.qml" << customFont;
129}
130
131void tst_font::font()
132{
133 QFETCH(QString, testFile);
134 QFETCH(QFont, expectedFont);
135
136 if (QSysInfo::productType().compare(other: QLatin1String("osx"), cs: Qt::CaseInsensitive) == 0
137 && qgetenv(varName: "QTEST_ENVIRONMENT").split(sep: ' ').contains(t: "CI")) {
138 QSKIP("This test crashes on macOS: QTBUG-70063");
139 }
140
141 QQmlEngine engine;
142 QQmlComponent component(&engine);
143 component.loadUrl(url: testFileUrl(fileName: testFile));
144
145 QScopedPointer<QObject> object(component.create());
146 QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
147
148 QVariant var = object->property(name: "font");
149 QVERIFY(var.isValid());
150
151 QFont actualFont = var.value<QFont>();
152 QCOMPARE(actualFont, expectedFont);
153}
154
155void tst_font::inheritance_data()
156{
157 QTest::addColumn<QString>(name: "testFile");
158
159 QTest::newRow(dataTag: "Control") << "inheritance-control.qml";
160 QTest::newRow(dataTag: "Child Control") << "inheritance-childcontrol.qml";
161 QTest::newRow(dataTag: "Dynamic Control") << "inheritance-dynamiccontrol.qml";
162 QTest::newRow(dataTag: "Dynamic Child Control") << "inheritance-dynamicchildcontrol.qml";
163
164 QTest::newRow(dataTag: "Popup") << "inheritance-popup.qml";
165 QTest::newRow(dataTag: "Child Popup") << "inheritance-childpopup.qml";
166 QTest::newRow(dataTag: "Dynamic Popup") << "inheritance-dynamicpopup.qml";
167 QTest::newRow(dataTag: "Dynamic Child Popup") << "inheritance-dynamicchildpopup.qml";
168}
169
170void tst_font::inheritance()
171{
172 QFETCH(QString, testFile);
173
174 QQmlEngine engine;
175 QQmlComponent component(&engine);
176 component.loadUrl(url: testFileUrl(fileName: testFile));
177
178 QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(object: component.create()));
179 QVERIFY2(!window.isNull(), qPrintable(component.errorString()));
180
181 QObject *control = window->property(name: "control").value<QObject *>();
182 QObject *child = window->property(name: "child").value<QObject *>();
183 QObject *grandChild = window->property(name: "grandChild").value<QObject *>();
184 QVERIFY(control && child && grandChild);
185
186 QCOMPARE(window->font(), QFont());
187
188 QCOMPARE(control->property("font").value<QFont>(), QFont());
189 QCOMPARE(child->property("font").value<QFont>(), QFont());
190 QCOMPARE(grandChild->property("font").value<QFont>(), QFont());
191
192 QFont childFont;
193 childFont.setFamily("Arial");
194 childFont.setPixelSize(80);
195 childFont.setItalic(true);
196 child->setProperty(name: "font", value: childFont);
197 QCOMPARE(child->property("font").value<QFont>(), childFont);
198 QCOMPARE(grandChild->property("font").value<QFont>(), childFont);
199
200 QFont grandChildFont(childFont);
201 grandChildFont.setFamily("Times New Roman");
202 grandChildFont.setUnderline(true);
203 grandChild->setProperty(name: "font", value: grandChildFont);
204 QCOMPARE(child->property("font").value<QFont>(), childFont);
205 QCOMPARE(grandChild->property("font").value<QFont>(), grandChildFont);
206
207 QFont windowFont;
208 windowFont.setWeight(QFont::Thin);
209 window->setFont(windowFont);
210 QCOMPARE(window->font(), windowFont);
211 QCOMPARE(control->property("font").value<QFont>(), windowFont);
212
213 childFont.setWeight(QFont::Thin);
214 QCOMPARE(child->property("font").value<QFont>(), childFont);
215
216 grandChildFont.setWeight(QFont::Thin);
217 QCOMPARE(grandChild->property("font").value<QFont>(), grandChildFont);
218
219 child->setProperty(name: "font", value: QVariant());
220 QCOMPARE(child->property("font").value<QFont>(), windowFont);
221 QCOMPARE(grandChild->property("font").value<QFont>(), grandChildFont);
222
223 grandChild->setProperty(name: "font", value: QVariant());
224 QCOMPARE(grandChild->property("font").value<QFont>(), windowFont);
225}
226
227class TestFontTheme : public QQuickTheme
228{
229public:
230 static const int NFonts = QQuickTheme::Tumbler + 1;
231
232 TestFontTheme()
233 {
234 for (int i = 0; i < NFonts; ++i) {
235 QFont font = QFont();
236 font.setPixelSize(i + 10);
237 setFont(scope: static_cast<Scope>(i), font);
238 }
239 }
240};
241
242Q_DECLARE_METATYPE(QQuickTheme::Scope)
243
244void tst_font::defaultFont_data()
245{
246 QTest::addColumn<QString>(name: "control");
247 QTest::addColumn<QQuickTheme::Scope>(name: "scope");
248
249 QTest::newRow(dataTag: "AbstractButton") << "AbstractButton" << QQuickTheme::System;
250 QTest::newRow(dataTag: "ApplicationWindow") << "ApplicationWindow" << QQuickTheme::System;
251 QTest::newRow(dataTag: "Button") << "Button" << QQuickTheme::Button;
252 QTest::newRow(dataTag: "CheckBox") << "CheckBox" << QQuickTheme::CheckBox;
253 QTest::newRow(dataTag: "CheckDelegate") << "CheckDelegate" << QQuickTheme::ListView;
254 QTest::newRow(dataTag: "ComboBox") << "ComboBox" << QQuickTheme::ComboBox;
255 QTest::newRow(dataTag: "Container") << "Container" << QQuickTheme::System;
256 QTest::newRow(dataTag: "Control") << "Control" << QQuickTheme::System;
257 QTest::newRow(dataTag: "Dial") << "Dial" << QQuickTheme::System;
258 QTest::newRow(dataTag: "Dialog") << "Dialog" << QQuickTheme::System;
259 QTest::newRow(dataTag: "DialogButtonBox") << "DialogButtonBox" << QQuickTheme::System;
260 QTest::newRow(dataTag: "Drawer") << "Drawer" << QQuickTheme::System;
261 QTest::newRow(dataTag: "Frame") << "Frame" << QQuickTheme::System;
262 QTest::newRow(dataTag: "GroupBox") << "GroupBox" << QQuickTheme::GroupBox;
263 QTest::newRow(dataTag: "ItemDelegate") << "ItemDelegate" << QQuickTheme::ItemView;
264 QTest::newRow(dataTag: "Label") << "Label" << QQuickTheme::Label;
265 QTest::newRow(dataTag: "Menu") << "Menu" << QQuickTheme::Menu;
266 QTest::newRow(dataTag: "MenuItem") << "MenuItem" << QQuickTheme::Menu;
267 QTest::newRow(dataTag: "MenuSeparator") << "MenuSeparator" << QQuickTheme::Menu;
268 QTest::newRow(dataTag: "Page") << "Page" << QQuickTheme::System;
269 QTest::newRow(dataTag: "Pane") << "Pane" << QQuickTheme::System;
270 QTest::newRow(dataTag: "Popup") << "Popup" << QQuickTheme::System;
271 QTest::newRow(dataTag: "ProgressBar") << "ProgressBar" << QQuickTheme::System;
272 QTest::newRow(dataTag: "RadioButton") << "RadioButton" << QQuickTheme::RadioButton;
273 QTest::newRow(dataTag: "RadioDelegate") << "RadioDelegate" << QQuickTheme::ListView;
274 QTest::newRow(dataTag: "RangeSlider") << "RangeSlider" << QQuickTheme::System;
275 QTest::newRow(dataTag: "RoundButton") << "RoundButton" << QQuickTheme::Button;
276 QTest::newRow(dataTag: "ScrollBar") << "ScrollBar" << QQuickTheme::System;
277 QTest::newRow(dataTag: "ScrollIndicator") << "ScrollIndicator" << QQuickTheme::System;
278 QTest::newRow(dataTag: "Slider") << "Slider" << QQuickTheme::System;
279 QTest::newRow(dataTag: "SpinBox") << "SpinBox" << QQuickTheme::SpinBox;
280 QTest::newRow(dataTag: "SwipeDelegate") << "SwipeDelegate" << QQuickTheme::ListView;
281 QTest::newRow(dataTag: "Switch") << "Switch" << QQuickTheme::Switch;
282 QTest::newRow(dataTag: "SwitchDelegate") << "SwitchDelegate" << QQuickTheme::ListView;
283 QTest::newRow(dataTag: "TabBar") << "TabBar" << QQuickTheme::TabBar;
284 QTest::newRow(dataTag: "TabButton") << "TabButton" << QQuickTheme::TabBar;
285 QTest::newRow(dataTag: "TextArea") << "TextArea" << QQuickTheme::TextArea;
286 QTest::newRow(dataTag: "TextField") << "TextField" << QQuickTheme::TextField;
287 QTest::newRow(dataTag: "ToolBar") << "ToolBar" << QQuickTheme::ToolBar;
288 QTest::newRow(dataTag: "ToolButton") << "ToolButton" << QQuickTheme::ToolBar;
289 QTest::newRow(dataTag: "ToolSeparator") << "ToolSeparator" << QQuickTheme::ToolBar;
290 QTest::newRow(dataTag: "ToolTip") << "ToolTip" << QQuickTheme::ToolTip;
291 QTest::newRow(dataTag: "Tumbler") << "Tumbler" << QQuickTheme::Tumbler;
292}
293
294void tst_font::defaultFont()
295{
296 QFETCH(QString, control);
297 QFETCH(QQuickTheme::Scope, scope);
298
299 QQmlEngine engine;
300 QQmlComponent component(&engine);
301 component.setData(QString("import QtQuick.Controls 2.2; %1 { }").arg(a: control).toUtf8(), baseUrl: QUrl());
302
303 // The call to setData() above causes QQuickDefaultTheme to be set as the current theme,
304 // so we must make sure we only set our theme afterwards.
305 QQuickThemePrivate::instance.reset(other: new TestFontTheme);
306
307 QScopedPointer<QObject> object(component.create());
308 QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
309
310 QVariant var = object->property(name: "font");
311 QVERIFY(var.isValid());
312
313 QFont expectedFont = QQuickTheme::font(scope);
314 QFont actualFont = var.value<QFont>();
315 QCOMPARE(actualFont, expectedFont);
316}
317
318void tst_font::listView_data()
319{
320 QTest::addColumn<QString>(name: "objectName");
321
322 QTest::newRow(dataTag: "Control") << "control";
323 QTest::newRow(dataTag: "Label") << "label";
324 QTest::newRow(dataTag: "TextArea") << "textarea";
325 QTest::newRow(dataTag: "TextField") << "textfield";
326}
327
328void tst_font::listView()
329{
330 QFETCH(QString, objectName);
331
332 QQmlEngine engine;
333 QQmlComponent component(&engine);
334 component.loadUrl(url: testFileUrl(fileName: "listview.qml"));
335
336 QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(object: component.create()));
337 QVERIFY2(!window.isNull(), qPrintable(component.errorString()));
338
339 window->show();
340 QVERIFY(QTest::qWaitForWindowActive(window.data()));
341
342 QQuickItem *listView = window->property(name: "listView").value<QQuickItem *>();
343 QVERIFY(listView);
344
345 QQuickItem *contentItem = listView->property(name: "contentItem").value<QQuickItem *>();
346 QVERIFY(contentItem);
347
348 QVERIFY(QMetaObject::invokeMethod(listView, "forceLayout"));
349
350 QQuickItem *column = contentItem->childItems().value(i: 0);
351 QVERIFY(column);
352
353 QQuickItem *control = column->property(name: objectName.toUtf8()).value<QQuickItem *>();
354 QVERIFY(control);
355
356 QCOMPARE(control->property("font").value<QFont>().pixelSize(), 55);
357}
358
359QTEST_MAIN(tst_font)
360
361#include "tst_font.moc"
362

source code of qtquickcontrols2/tests/auto/font/tst_font.cpp