1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 #include <QtTest/QtTest>
46 #include <QMetaObject>
48 #include <private/qstylesheetstyle_p.h>
49 #include "../../../platformquirks.h"
51 class tst_QStyleSheetStyle : public QObject
55 tst_QStyleSheetStyle();
56 ~tst_QStyleSheetStyle();
61 void widgetsBeforeAppStyleSheet();
62 void widgetsAfterAppStyleSheet();
63 void applicationStyleSheet();
64 void windowStyleSheet();
65 void widgetStyleSheet();
66 void reparentWithNoChildStyleSheet();
67 void reparentWithChildStyleSheet();
68 void dynamicProperty();
69 // NB! Invoking this slot after layoutSpacing crashes on Mac.
75 void palettePropagation();
76 void fontPropagation();
77 void onWidgetDestroyed();
78 void fontPrecedence();
83 void attributesList();
85 void task206238_twice();
88 void dialogButtonBox();
89 void emptyStyleSheet();
92 void opaquePaintEvent_data();
93 void opaquePaintEvent();
94 void complexWidgetFocus();
95 void task188195_baseBackground();
96 void task232085_spinBoxLineEditBg();
97 void changeStyleInChangeEvent();
98 void QTBUG15910_crashNullWidget();
100 //at the end because it mess with the style.
103 void QTBUG11658_cachecrash();
105 QColor COLOR(const QWidget& w) {
107 return w.palette().color(w.foregroundRole());
109 QColor APPCOLOR(const QWidget& w) {
111 return qApp->palette(&w).color(w.foregroundRole());
113 QColor BACKGROUND(const QWidget& w) {
115 return w.palette().color(w.backgroundRole());
117 QColor APPBACKGROUND(const QWidget& w) {
119 return qApp->palette(&w).color(w.backgroundRole());
121 int FONTSIZE(const QWidget &w) {
123 return w.font().pointSize();
125 int APPFONTSIZE(const QWidget &w) {
126 return qApp->font(&w).pointSize();
130 tst_QStyleSheetStyle::tst_QStyleSheetStyle()
134 tst_QStyleSheetStyle::~tst_QStyleSheetStyle()
138 void tst_QStyleSheetStyle::numinstances()
141 QCommonStyle *style = new QCommonStyle;
142 style->setParent(&w);
146 // set and unset application stylesheet
147 QCOMPARE(QStyleSheetStyle::numinstances, 0);
148 qApp->setStyleSheet("* { color: red; }");
149 QCOMPARE(QStyleSheetStyle::numinstances, 1);
150 qApp->setStyleSheet("");
151 QCOMPARE(QStyleSheetStyle::numinstances, 0);
153 // set and unset application stylesheet+widget
154 qApp->setStyleSheet("* { color: red; }");
155 w.setStyleSheet("color: red;");
156 QCOMPARE(QStyleSheetStyle::numinstances, 2);
158 QCOMPARE(QStyleSheetStyle::numinstances, 2);
159 qApp->setStyleSheet("");
160 QCOMPARE(QStyleSheetStyle::numinstances, 1);
162 QCOMPARE(QStyleSheetStyle::numinstances, 0);
164 // set and unset widget stylesheet
166 w.setStyleSheet("color: red");
167 QCOMPARE(QStyleSheetStyle::numinstances, 1);
169 QCOMPARE(QStyleSheetStyle::numinstances, 2);
171 QCOMPARE(QStyleSheetStyle::numinstances, 0);
174 void tst_QStyleSheetStyle::widgetsBeforeAppStyleSheet()
176 QPushButton w1; // widget with no stylesheet
177 qApp->setStyleSheet("* { color: red; }");
178 QVERIFY(COLOR(w1) == QColor("red"));
179 w1.setStyleSheet("color: white");
180 QVERIFY(COLOR(w1) == QColor("white"));
181 qApp->setStyleSheet("");
182 QVERIFY(COLOR(w1) == QColor("white"));
183 w1.setStyleSheet("");
184 QVERIFY(COLOR(w1) == APPCOLOR(w1));
187 class FriendlySpinBox : public QSpinBox { friend class tst_QStyleSheetStyle; };
189 void tst_QStyleSheetStyle::widgetsAfterAppStyleSheet()
191 qApp->setStyleSheet("* { color: red; font-size: 32pt; }");
193 FriendlySpinBox spin;
194 QVERIFY(COLOR(w1) == QColor("red"));
195 QVERIFY(COLOR(spin) == QColor("red"));
196 QVERIFY(COLOR(*spin.lineEdit()) == QColor("red"));
197 QCOMPARE(FONTSIZE(w1), 32);
198 QCOMPARE(FONTSIZE(spin), 32);
199 QCOMPARE(FONTSIZE(*spin.lineEdit()), 32);
200 w1.setStyleSheet("color: white");
201 QVERIFY(COLOR(w1) == QColor("white"));
202 QVERIFY(COLOR(spin) == QColor("red"));
203 QVERIFY(COLOR(*spin.lineEdit()) == QColor("red"));
204 w1.setStyleSheet("");
205 QVERIFY(COLOR(w1) == QColor("red"));
206 QVERIFY(COLOR(spin) == QColor("red"));
207 QVERIFY(COLOR(*spin.lineEdit()) == QColor("red"));
208 w1.setStyleSheet("color: white");
209 QVERIFY(COLOR(w1) == QColor("white"));
210 qApp->setStyleSheet("");
211 QVERIFY(COLOR(w1) == QColor("white"));
212 QVERIFY(COLOR(spin) == APPCOLOR(spin));
213 QVERIFY(COLOR(*spin.lineEdit()) == APPCOLOR(*spin.lineEdit()));
214 w1.setStyleSheet("");
215 QVERIFY(COLOR(w1) == APPCOLOR(w1));
216 // QCOMPARE(FONTSIZE(w1), APPFONTSIZE(w1)); //### task 244261
217 QCOMPARE(FONTSIZE(spin), APPFONTSIZE(spin));
218 //QCOMPARE(FONTSIZE(*spin.lineEdit()), APPFONTSIZE(*spin.lineEdit())); //### task 244261
221 void tst_QStyleSheetStyle::applicationStyleSheet()
224 qApp->setStyleSheet("* { color: red; }");
225 QVERIFY(COLOR(w1) == QColor("red"));
226 qApp->setStyleSheet("* { color: white; }");
227 QVERIFY(COLOR(w1) == QColor("white"));
228 qApp->setStyleSheet("");
229 QVERIFY(COLOR(w1) == APPCOLOR(w1));
230 qApp->setStyleSheet("* { color: red }");
231 QVERIFY(COLOR(w1) == QColor("red"));
234 void tst_QStyleSheetStyle::windowStyleSheet()
237 qApp->setStyleSheet("");
238 w1.setStyleSheet("* { color: red; }");
239 QVERIFY(COLOR(w1) == QColor("red"));
240 w1.setStyleSheet("* { color: white; }");
241 QVERIFY(COLOR(w1) == QColor("white"));
242 w1.setStyleSheet("");
243 QVERIFY(COLOR(w1) == APPCOLOR(w1));
244 w1.setStyleSheet("* { color: red }");
245 QVERIFY(COLOR(w1) == QColor("red"));
247 qApp->setStyleSheet("* { color: green }");
248 QVERIFY(COLOR(w1) == QColor("red"));
249 w1.setStyleSheet("");
250 QVERIFY(COLOR(w1) == QColor("green"));
251 qApp->setStyleSheet("");
252 QVERIFY(COLOR(w1) == APPCOLOR(w1));
255 void tst_QStyleSheetStyle::widgetStyleSheet()
258 QPushButton *pb = new QPushButton(&w1);
259 QPushButton &w2 = *pb;
261 qApp->setStyleSheet("");
262 w1.setStyleSheet("* { color: red }");
263 QVERIFY(COLOR(w1) == QColor("red"));
264 QVERIFY(COLOR(w2) == QColor("red"));
266 w2.setStyleSheet("* { color: white }");
267 QVERIFY(COLOR(w2) == QColor("white"));
269 w1.setStyleSheet("* { color: blue }");
270 QVERIFY(COLOR(w1) == QColor("blue"));
271 QVERIFY(COLOR(w2) == QColor("white"));
273 w1.setStyleSheet("");
274 QVERIFY(COLOR(w1) == APPCOLOR(w1));
275 QVERIFY(COLOR(w2) == QColor("white"));
277 w2.setStyleSheet("");
278 QVERIFY(COLOR(w1) == APPCOLOR(w1));
279 QVERIFY(COLOR(w2) == APPCOLOR(w2));
282 void tst_QStyleSheetStyle::reparentWithNoChildStyleSheet()
285 QPushButton *pb = new QPushButton(&p1);
286 QPushButton &c1 = *pb; // child with no stylesheet
288 qApp->setStyleSheet("");
289 p1.setStyleSheet("* { color: red }");
290 QVERIFY(COLOR(c1) == QColor("red"));
292 QVERIFY(COLOR(c1) == APPCOLOR(c1));
294 p2.setStyleSheet("* { color: white }");
295 QVERIFY(COLOR(c1) == QColor("white"));
298 QVERIFY(COLOR(c1) == QColor("red"));
300 qApp->setStyleSheet("* { color: blue }");
302 QVERIFY(COLOR(c1) == QColor("blue"));
306 void tst_QStyleSheetStyle::reparentWithChildStyleSheet()
308 qApp->setStyleSheet("");
310 QPushButton *pb = new QPushButton(&p1);
311 QPushButton &c1 = *pb;
313 c1.setStyleSheet("background: gray");
314 QVERIFY(BACKGROUND(c1) == QColor("gray"));
316 QVERIFY(BACKGROUND(c1) == QColor("gray"));
318 qApp->setStyleSheet("* { color: white }");
320 QVERIFY(BACKGROUND(c1) == QColor("gray"));
321 QVERIFY(COLOR(c1) == QColor("white"));
324 void tst_QStyleSheetStyle::repolish()
326 qApp->setStyleSheet("");
328 p1.setStyleSheet("color: red; background: white");
329 QVERIFY(BACKGROUND(p1) == QColor("white"));
330 p1.setStyleSheet("background: white");
331 QVERIFY(COLOR(p1) == APPCOLOR(p1));
332 p1.setStyleSheet("color: red");
333 QVERIFY(COLOR(p1) == QColor("red"));
334 QVERIFY(BACKGROUND(p1) == APPBACKGROUND(p1));
335 p1.setStyleSheet("");
336 QVERIFY(COLOR(p1) == APPCOLOR(p1));
337 QVERIFY(BACKGROUND(p1) == APPBACKGROUND(p1));
340 void tst_QStyleSheetStyle::widgetStyle()
342 qApp->setStyleSheet("");
344 QWidget *window1 = new QWidget;
345 window1->setObjectName("window1");
346 QWidget *widget1 = new QWidget(window1);
347 widget1->setObjectName("widget1");
348 QWidget *widget2 = new QWidget;
349 widget2->setObjectName("widget2");
350 QWidget *window2 = new QWidget;
351 window2->setObjectName("window2");
352 window1->ensurePolished();
353 window2->ensurePolished();
354 widget1->ensurePolished();
355 widget2->ensurePolished();
357 QWindowsStyle style1, style2;
358 QPointer<QStyle> pstyle1 = &style1;
359 QPointer<QStyle> pstyle2 = &style2;
361 QStyle *appStyle = qApp->style();
363 // Sanity: By default, a window inherits the application style
364 QCOMPARE(appStyle, window1->style());
366 // Setting a custom style on a widget
367 window1->setStyle(&style1);
368 QCOMPARE(static_cast<QStyle *>(&style1), window1->style());
370 // Setting another style must not delete the older style
371 window1->setStyle(&style2);
372 QCOMPARE(static_cast<QStyle *>(&style2), window1->style());
373 QVERIFY(!pstyle1.isNull()); // case we have not already crashed
375 // Setting null style must make it follow the qApp style
376 window1->setStyle(0);
377 QCOMPARE(window1->style(), appStyle);
378 QVERIFY(!pstyle2.isNull()); // case we have not already crashed
379 QVERIFY(!pstyle2.isNull()); // case we have not already crashed
381 // Sanity: Set the stylesheet
382 window1->setStyleSheet(":x { }");
384 QPointer<QStyleSheetStyle> proxy = (QStyleSheetStyle *)window1->style();
385 QVERIFY(!proxy.isNull());
386 QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle"); // must be our proxy
387 QVERIFY(proxy->base == 0); // and follows the application
389 // Set the stylesheet
390 window1->setStyle(&style1);
391 QVERIFY(proxy.isNull()); // we create a new one each time
392 proxy = (QStyleSheetStyle *)window1->style();
393 QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle"); // it is a proxy
394 QCOMPARE(proxy->baseStyle(), static_cast<QStyle *>(&style1)); // must have been replaced with the new one
396 // Update the stylesheet and check nothing changes
397 window1->setStyleSheet(":y { }");
398 QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle"); // it is a proxy
399 QCOMPARE(proxy->baseStyle(), static_cast<QStyle *>(&style1)); // the same guy
401 // Remove the stylesheet
402 proxy = (QStyleSheetStyle *)window1->style();
403 window1->setStyleSheet("");
404 QVERIFY(proxy.isNull()); // should have disappeared
405 QCOMPARE(window1->style(), static_cast<QStyle *>(&style1)); // its restored
407 // Style Sheet existing children propagation
408 window1->setStyleSheet(":z { }");
409 proxy = (QStyleSheetStyle *)window1->style();
410 QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle");
411 QCOMPARE(window1->style(), widget1->style()); // proxy must have propagated
412 QCOMPARE(widget2->style(), appStyle); // widget2 is following the app style
414 // Style Sheet automatic propagation to new children
415 widget2->setParent(window1); // reparent in!
416 QCOMPARE(window1->style(), widget2->style()); // proxy must have propagated
418 // Style Sheet automatic removal from children who abandoned their parents
419 window2->setStyle(&style2);
420 widget2->setParent(window2); // reparent
421 QCOMPARE(widget2->style(), appStyle); // widget2 is following the app style
423 // Style Sheet propagation on a child widget with a custom style
424 widget2->setStyle(&style1);
425 window2->setStyleSheet(":x { }");
426 proxy = (QStyleSheetStyle *)widget2->style();
427 QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle");
428 QCOMPARE(proxy->baseStyle(), static_cast<QStyle *>(&style1));
430 // Style Sheet propagation on a child widget with a custom style already set
431 window2->setStyleSheet("");
432 QCOMPARE(window2->style(), static_cast<QStyle *>(&style2));
433 QCOMPARE(widget2->style(), static_cast<QStyle *>(&style1));
434 widget2->setStyle(0);
435 window2->setStyleSheet(":x { }");
436 widget2->setStyle(&style1);
437 proxy = (QStyleSheetStyle *)widget2->style();
438 QCOMPARE(proxy->metaObject()->className(), "QStyleSheetStyle");
440 // QApplication, QWidget both having a style sheet
442 // clean everything out
443 window1->setStyle(0);
444 window1->setStyleSheet("");
445 window2->setStyle(0);
446 window2->setStyleSheet("");
449 qApp->setStyleSheet("may_insanity_prevail { }"); // app has stylesheet
450 QCOMPARE(window1->style(), qApp->style());
451 QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle");
452 QCOMPARE(widget1->style()->metaObject()->className(), "QStyleSheetStyle"); // check the child
453 window1->setStyleSheet("may_more_insanity_prevail { }"); // window has stylesheet
454 QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle"); // a new one
455 QCOMPARE(widget1->style(), window1->style()); // child follows...
456 proxy = (QStyleSheetStyle *) window1->style();
457 QWindowsStyle *newStyle = new QWindowsStyle;
458 qApp->setStyle(newStyle); // set a custom style on app
459 proxy = (QStyleSheetStyle *) window1->style();
460 QCOMPARE(proxy->baseStyle(), static_cast<QStyle *>(newStyle)); // magic ;) the widget still follows the application
461 QCOMPARE(static_cast<QStyle *>(proxy), widget1->style()); // child still follows...
463 window1->setStyleSheet(""); // remove stylesheet
464 QCOMPARE(window1->style(), qApp->style()); // is this cool or what
465 QCOMPARE(widget1->style(), qApp->style()); // annoying child follows...
466 QWindowsStyle wndStyle;
467 window1->setStyle(&wndStyle);
468 QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle"); // auto wraps it
469 QCOMPARE(widget1->style(), window1->style()); // and auto propagates to child
470 qApp->setStyleSheet(""); // remove the app stylesheet
471 QCOMPARE(window1->style(), static_cast<QStyle *>(&wndStyle)); // auto dewrap
472 QCOMPARE(widget1->style(), qApp->style()); // and child state is restored
473 window1->setStyle(0); // let sanity prevail
481 void tst_QStyleSheetStyle::appStyle()
483 qApp->setStyleSheet("");
484 // qApp style can never be 0
485 QVERIFY(QApplication::style() != 0);
486 QPointer<QStyle> style1 = new QWindowsStyle;
487 QPointer<QStyle> style2 = new QWindowsStyle;
488 qApp->setStyle(style1);
490 QVERIFY(qApp->style() == style1);
491 qApp->setStyle(style2);
492 QVERIFY(style1.isNull()); // qApp must have taken ownership and deleted it
493 // Setting null should not crash
495 QVERIFY(qApp->style() == style2);
497 // Set the stylesheet
498 qApp->setStyleSheet("whatever");
499 QPointer<QStyleSheetStyle> sss = (QStyleSheetStyle *)qApp->style();
500 QVERIFY(!sss.isNull());
501 QCOMPARE(sss->metaObject()->className(), "QStyleSheetStyle"); // must be our proxy now
502 QVERIFY(!style2.isNull()); // this should exist as it is the base of the proxy
503 QVERIFY(sss->baseStyle() == style2);
504 style1 = new QWindowsStyle;
505 qApp->setStyle(style1);
506 QVERIFY(style2.isNull()); // should disappear automatically
507 QVERIFY(sss.isNull()); // should disappear automatically
509 // Update the stylesheet and check nothing changes
510 sss = (QStyleSheetStyle *)qApp->style();
511 qApp->setStyleSheet("whatever2");
512 QVERIFY(qApp->style() == sss);
513 QVERIFY(sss->baseStyle() == style1);
515 // Revert the stylesheet
516 qApp->setStyleSheet("");
517 QVERIFY(sss.isNull()); // should have disappeared
518 QVERIFY(qApp->style() == style1);
520 qApp->setStyleSheet("");
521 QVERIFY(qApp->style() == style1);
524 void tst_QStyleSheetStyle::dynamicProperty()
526 qApp->setStyleSheet(QString());
528 QString appStyle = qApp->style()->metaObject()->className();
529 QPushButton pb1, pb2;
530 pb1.setProperty("type", "critical");
531 qApp->setStyleSheet("*[class~=\"QPushButton\"] { color: red; } *[type=\"critical\"] { background: white; }");
532 QVERIFY(COLOR(pb1) == Qt::red);
533 QVERIFY(BACKGROUND(pb1) == Qt::white);
535 pb2.setProperty("class", "critical"); // dynamic class
536 pb2.setStyleSheet(QLatin1String(".critical[style~=\"") + appStyle + "\"] { color: blue }");
539 QVERIFY(COLOR(pb2) == Qt::blue);
543 void tst_QStyleSheetStyle::layoutSpacing()
545 qApp->setStyleSheet("* { color: red }");
549 int spacing_widgetstyle = window.style()->layoutSpacing(ck1.sizePolicy().controlType(), ck2.sizePolicy().controlType(), Qt::Vertical);
550 int spacing_style = window.style()->layoutSpacing(ck1.sizePolicy().controlType(), ck2.sizePolicy().controlType(), Qt::Vertical);
551 QCOMPARE(spacing_widgetstyle, spacing_style);
555 void tst_QStyleSheetStyle::qproperty()
558 pb.setStyleSheet("QPushButton { qproperty-text: hello; qproperty-checkable: 1; qproperty-checked: false}");
560 QCOMPARE(pb.text(), QString("hello"));
561 QCOMPARE(pb.isCheckable(), true);
562 QCOMPARE(pb.isChecked(), false);
566 class PushButton1 : public QPushButton {
571 class PushButton2 : public PushButton1 {
574 PushButton2() { setProperty("class", "PushButtonTwo PushButtonDuo"); }
578 void tst_QStyleSheetStyle::namespaces()
581 qApp->setStyleSheet("ns--PushButton1 { background: white }");
582 QVERIFY(BACKGROUND(pb1) == QColor("white"));
583 qApp->setStyleSheet(".ns--PushButton1 { background: red }");
584 QVERIFY(BACKGROUND(pb1) == QColor("red"));
587 qApp->setStyleSheet("ns--PushButton1 { background: blue}");
588 QVERIFY(BACKGROUND(pb2) == QColor("blue"));
589 qApp->setStyleSheet("ns--PushButton2 { background: magenta }");
590 QVERIFY(BACKGROUND(pb2) == QColor("magenta"));
591 qApp->setStyleSheet(".PushButtonTwo { background: white; }");
592 QVERIFY(BACKGROUND(pb2) == QColor("white"));
593 qApp->setStyleSheet(".PushButtonDuo { background: red; }");
594 QVERIFY(BACKGROUND(pb2) == QColor("red"));
597 void tst_QStyleSheetStyle::palettePropagation()
599 qApp->setStyleSheet("");
601 QPushButton *push = new QPushButton(&gb);
602 QPushButton &pb = *push;
603 push->setText("AsdF");
605 gb.setStyleSheet("QGroupBox { color: red }");
606 QVERIFY(COLOR(gb) == Qt::red);
607 QVERIFY(COLOR(pb) == APPCOLOR(pb)); // palette shouldn't propagate
608 gb.setStyleSheet("QGroupBox * { color: red }");
610 QVERIFY(COLOR(pb) == Qt::red);
611 QVERIFY(COLOR(gb) == APPCOLOR(gb));
614 window.setStyleSheet("* { color: white; }");
615 pb.setParent(&window);
616 QVERIFY(COLOR(pb) == Qt::white);
619 void tst_QStyleSheetStyle::fontPropagation()
621 qApp->setStyleSheet("");
626 QAbstractItemView *popup = cb.view();
627 int viewFontSize = FONTSIZE(*popup);
629 cb.setStyleSheet("QComboBox { font-size: 20pt; }");
630 QVERIFY(FONTSIZE(cb) == 20);
631 QVERIFY(FONTSIZE(*popup) == viewFontSize);
633 QPushButton *push = new QPushButton(&gb);
634 QPushButton &pb = *push;
635 int buttonFontSize = FONTSIZE(pb);
636 int gbFontSize = FONTSIZE(gb);
638 gb.setStyleSheet("QGroupBox { font-size: 20pt }");
639 QVERIFY(FONTSIZE(gb) == 20);
640 QVERIFY(FONTSIZE(pb) == buttonFontSize); // font does not propagate
641 gb.setStyleSheet("QGroupBox * { font-size: 20pt; }");
642 QVERIFY(FONTSIZE(gb) == gbFontSize);
643 QVERIFY(FONTSIZE(pb) == 20);
646 window.setStyleSheet("* { font-size: 10pt }");
647 pb.setParent(&window);
648 QCOMPARE(FONTSIZE(pb), 10);
649 window.setStyleSheet("");
650 QVERIFY(FONTSIZE(pb) == buttonFontSize);
653 tw.setStyleSheet("QTabWidget { font-size: 20pt; }");
654 QVERIFY(FONTSIZE(tw) == 20);
655 QWidget *child = qFindChild<QWidget *>(&tw, "qt_tabwidget_tabbar");
656 QVERIFY2(child, "QTabWidget did not contain a widget named \"qt_tabwidget_tabbar\"");
657 QVERIFY(FONTSIZE(*child) == 20);
660 void tst_QStyleSheetStyle::onWidgetDestroyed()
662 qApp->setStyleSheet("");
663 QLabel *l = new QLabel;
664 l->setStyleSheet("QLabel { color: red }");
665 QPointer<QStyleSheetStyle> ss = (QStyleSheetStyle *) l->style();
667 QVERIFY(ss.isNull());
670 void tst_QStyleSheetStyle::fontPrecedence()
675 QVERIFY(FONTSIZE(edit) != 22); // Sanity check to make sure this test makes sense.
676 edit.setStyleSheet("QLineEdit { font-size: 22pt; }");
677 QCOMPARE(FONTSIZE(edit), 22);
678 font.setPointSize(16);
680 QCOMPARE(FONTSIZE(edit), 22);
681 edit.setStyleSheet("");
682 QCOMPARE(FONTSIZE(edit), 16);
683 font.setPointSize(18);
685 QCOMPARE(FONTSIZE(edit), 18);
686 edit.setStyleSheet("QLineEdit { font-size: 20pt; }");
687 QCOMPARE(FONTSIZE(edit), 20);
688 edit.setStyleSheet("");
689 QCOMPARE(FONTSIZE(edit), 18);
693 edit2.setReadOnly(true);
694 edit2.setStyleSheet("QLineEdit { font-size: 24pt; } QLineEdit:read-only { font-size: 26pt; }");
695 QCOMPARE(FONTSIZE(edit2), 26);
698 // Ensure primary will only return true if the color covers more than 50% of pixels
699 static bool testForColors(const QImage& image, const QColor& color, bool ensurePrimary=false)
702 QRgb rgb = color.rgba();
703 int totalCount = image.height()*image.width();
704 for (int y = 0; y < image.height(); ++y) {
705 for (int x = 0; x < image.width(); ++x) {
706 // Because of antialiasing we allow a certain range of errors here.
707 QRgb pixel = image.pixel(x, y);
709 if (qAbs((int)(pixel & 0xff) - (int)(rgb & 0xff)) +
710 qAbs((int)((pixel & 0xff00) >> 8) - (int)((rgb & 0xff00) >> 8)) +
711 qAbs((int)((pixel & 0xff0000) >> 16) - (int)((rgb & 0xff0000) >> 16)) <= 50) {
713 if (!ensurePrimary && count >=10 )
715 else if (count > totalCount/2)
724 void tst_QStyleSheetStyle::focusColors()
726 // Tests if colors can be changed by altering the focus of the widget.
727 // To avoid messy pixel-by-pixel comparison, we assume that the goal
728 // is reached if at least ten pixels of the right color can be found in
730 // For this reason, we use unusual and extremely ugly colors! :-)
731 // Note that in case of anti-aliased text, ensuring that we have at least
732 // ten pixels of the right color requires quite a many characters, as the
733 // majority of the pixels will have slightly different colors due to the
734 // anti-aliasing effect.
735 #if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC) && !(defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL))
736 QSKIP("This is a fragile test which fails on many esoteric platforms because of focus problems. "
737 "That doesn't mean that the feature doesn't work in practice.");
739 QList<QWidget *> widgets;
740 widgets << new QPushButton("TESTING TESTING");
741 widgets << new QLineEdit("TESTING TESTING");
742 widgets << new QLabel("TESTING TESTING");
743 QSpinBox *spinbox = new QSpinBox;
744 spinbox->setMaximum(1000000000);
745 spinbox->setValue(123456789);
747 QComboBox *combobox = new QComboBox;
748 combobox->setEditable(true);
749 combobox->addItems(QStringList() << "TESTING TESTING");
751 widgets << new QLabel("TESTING TESTING");
754 // QWS has its own special focus logic which is slightly different
755 // and I don't dare change it at this point, because someone will
756 // be relying on it. It means that setFocus() on a NoFocus widget (i.e.
757 // a QLabel) will not work before the window is activated.
758 widgets[2]->setFocusPolicy(Qt::StrongFocus);
761 foreach (QWidget *widget, widgets) {
763 QLayout* layout = new QGridLayout;
765 QLineEdit* dummy = new QLineEdit; // Avoids initial focus.
767 widget->setStyleSheet("*:focus { border:none; background: #e8ff66; color: #ff0084 }");
769 layout->addWidget(dummy);
770 layout->addWidget(widget);
771 frame.setLayout(layout);
774 QApplication::setActiveWindow(&frame);
775 QVERIFY(QTest::qWaitForWindowActive(&frame));
777 QApplication::processEvents();
779 QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
780 frame.render(&image);
781 if (image.depth() < 24)
782 QSKIP("Test doesn't support color depth < 24");
784 QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
785 (QString::fromLatin1(widget->metaObject()->className())
786 + " did not contain background color #e8ff66, using style "
787 + QString::fromLatin1(qApp->style()->metaObject()->className()))
788 .toLocal8Bit().constData());
789 QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
790 (QString::fromLatin1(widget->metaObject()->className())
791 + " did not contain text color #ff0084, using style "
792 + QString::fromLatin1(qApp->style()->metaObject()->className()))
793 .toLocal8Bit().constData());
797 void tst_QStyleSheetStyle::hoverColors()
799 if (!PlatformQuirks::haveMouseCursor())
800 QSKIP("No mouse Cursor on this platform");
801 QList<QWidget *> widgets;
802 widgets << new QPushButton("TESTING TESTING");
803 widgets << new QLineEdit("TESTING TESTING");
804 widgets << new QLabel("TESTING TESTING");
805 QSpinBox *spinbox = new QSpinBox;
806 spinbox->setMaximum(1000000000);
807 spinbox->setValue(123456789);
809 QComboBox *combobox = new QComboBox;
810 combobox->setEditable(true);
811 combobox->addItems(QStringList() << "TESTING TESTING");
813 widgets << new QLabel("<b>TESTING TESTING</b>");
815 foreach (QWidget *widget, widgets) {
816 //without Qt::X11BypassWindowManagerHint the window manager may move the window after we moved the cursor
817 QDialog frame(0, Qt::X11BypassWindowManagerHint);
818 QLayout* layout = new QGridLayout;
820 QLineEdit* dummy = new QLineEdit;
822 widget->setStyleSheet("*:hover { border:none; background: #e8ff66; color: #ff0084 }");
824 layout->addWidget(dummy);
825 layout->addWidget(widget);
826 frame.setLayout(layout);
830 //QWS does not implement enter/leave when windows are shown underneath the cursor
831 QCursor::setPos(QPoint(0,0));
834 QApplication::setActiveWindow(&frame);
835 QVERIFY(QTest::qWaitForWindowActive(&frame));
836 //move the mouse inside the widget, it should be colored
837 QTest::mouseMove ( widget, QPoint(6,6));
841 QEXPECT_FAIL("", "Numerous failures related to Qt::WA_UnderMouse, see QTBUGT-23685", Continue);
843 QVERIFY(widget->testAttribute(Qt::WA_UnderMouse));
845 QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
846 frame.render(&image);
849 QEXPECT_FAIL("", "Numerous failures related to Qt::WA_UnderMouse, see QTBUGT-23685", Continue);
851 QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
852 (QString::fromLatin1(widget->metaObject()->className())
853 + " did not contain background color #e8ff66").toLocal8Bit().constData());
855 QEXPECT_FAIL("", "Numerous failures related to Qt::WA_UnderMouse, see QTBUGT-23685", Continue);
857 QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
858 (QString::fromLatin1(widget->metaObject()->className())
859 + " did not contain text color #ff0084").toLocal8Bit().constData());
861 //move the mouse outside the widget, it should NOT be colored
862 QTest::mouseMove ( dummy, QPoint(5,5));
865 frame.render(&image);
867 QVERIFY2(!testForColors(image, QColor(0xe8, 0xff, 0x66)),
868 (QString::fromLatin1(widget->metaObject()->className())
869 + " did contain background color #e8ff66").toLocal8Bit().constData());
870 QVERIFY2(!testForColors(image, QColor(0xff, 0x00, 0x84)),
871 (QString::fromLatin1(widget->metaObject()->className())
872 + " did contain text color #ff0084").toLocal8Bit().constData());
874 //move the mouse again inside the widget, it should be colored
875 QTest::mouseMove (widget, QPoint(5,5));
878 QVERIFY(widget->testAttribute(Qt::WA_UnderMouse));
880 frame.render(&image);
882 QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
883 (QString::fromLatin1(widget->metaObject()->className())
884 + " did not contain background color #e8ff66").toLocal8Bit().constData());
886 if (qobject_cast<QComboBox *>(widget))
887 QEXPECT_FAIL("", "Failure only for QPushButton and QComboBox, see QTBUG-23686", Continue);
889 QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
890 (QString::fromLatin1(widget->metaObject()->className())
891 + " did not contain text color #ff0084").toLocal8Bit().constData());
896 class SingleInheritanceDialog : public QDialog
900 SingleInheritanceDialog(QWidget *w = 0) :
906 class DoubleInheritanceDialog : public SingleInheritanceDialog
910 DoubleInheritanceDialog(QWidget *w = 0) :
911 SingleInheritanceDialog(w)
916 void tst_QStyleSheetStyle::background()
918 const int number = 4;
919 QWidget* widgets[number];
920 // Testing inheritance styling of QDialog.
921 widgets[0] = new SingleInheritanceDialog;
922 widgets[0]->setStyleSheet("* { background-color: #e8ff66; }");
923 widgets[1] = new DoubleInheritanceDialog;
924 widgets[1]->setStyleSheet("* { background-color: #e8ff66; }");
926 // Testing gradients in QComboBox.
930 widgets[2] = new QDialog;
931 layout = new QGridLayout;
933 cb->setStyleSheet("* { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #e8ff66, stop:1 #000000); }");
934 layout->addWidget(cb);
935 widgets[2]->setLayout(layout);
937 widgets[3] = new QDialog;
938 layout = new QGridLayout;
940 cb->setStyleSheet("* { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #e8ff66, stop:1 #000000); }");
941 layout->addWidget(cb);
942 widgets[3]->setLayout(layout);
944 for (int c = 0; c < number; ++c) {
945 QWidget* widget = widgets[c];
948 QVERIFY(QTest::qWaitForWindowExposed(widget));
950 QImage image(widget->width(), widget->height(), QImage::Format_ARGB32);
951 widget->render(&image);
952 if (image.depth() < 24)
953 QSKIP("Test doesn't support color depth < 24");
955 QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
956 (QString::fromLatin1(widget->metaObject()->className())
957 + " did not contain background image with color #e8ff66")
958 .toLocal8Bit().constData());
964 void tst_QStyleSheetStyle::tabAlignement()
967 QTabWidget tabWidget(&topLevel);
968 tabWidget.addTab(new QLabel("tab1"),"tab1");
969 tabWidget.resize(QSize(400,400));
971 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
972 QTabBar *bar = qFindChild<QTabBar*>(&tabWidget);
974 //check the tab is on the right
975 tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: right ; }");
976 qApp->processEvents();
977 QVERIFY(bar->geometry().right() > 380);
978 QVERIFY(bar->geometry().left() > 200);
979 //check the tab is on the middle
980 tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: center ; }");
981 QVERIFY(bar->geometry().right() < 300);
982 QVERIFY(bar->geometry().left() > 100);
983 //check the tab is on the left
984 tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: left ; }");
985 QVERIFY(bar->geometry().left() < 20);
986 QVERIFY(bar->geometry().right() < 200);
988 tabWidget.setTabPosition(QTabWidget::West);
989 //check the tab is on the top
990 QVERIFY(bar->geometry().top() < 20);
991 QVERIFY(bar->geometry().bottom() < 200);
992 //check the tab is on the bottom
993 tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: right ; }");
994 QVERIFY(bar->geometry().bottom() > 380);
995 QVERIFY(bar->geometry().top() > 200);
996 //check the tab is on the middle
997 tabWidget.setStyleSheet("QTabWidget::tab-bar { alignment: center ; }");
998 QVERIFY(bar->geometry().bottom() < 300);
999 QVERIFY(bar->geometry().top() > 100);
1002 void tst_QStyleSheetStyle::attributesList()
1005 QPushButton *p1=new QPushButton(&w);
1006 QPushButton *p2=new QPushButton(&w);
1007 QPushButton *p3=new QPushButton(&w);
1008 QPushButton *p4=new QPushButton(&w);
1009 p1->setProperty("prop", QStringList() << "red");
1010 p2->setProperty("prop", QStringList() << "foo" << "red");
1011 p3->setProperty("prop", QStringList() << "foo" << "bar");
1013 w.setStyleSheet(" QPushButton{ background-color:blue; } QPushButton[prop~=red] { background-color:red; }");
1014 QCOMPARE(BACKGROUND(*p1) , QColor("red"));
1015 QCOMPARE(BACKGROUND(*p2) , QColor("red"));
1016 QCOMPARE(BACKGROUND(*p3) , QColor("blue"));
1017 QCOMPARE(BACKGROUND(*p4) , QColor("blue"));
1020 void tst_QStyleSheetStyle::minmaxSizes()
1022 QTabWidget tabWidget;
1023 tabWidget.setObjectName("tabWidget");
1024 int index1 = tabWidget.addTab(new QLabel("Tab1"),"a");
1026 QWidget *page2=new QLabel("page2");
1027 page2->setObjectName("page2");
1028 page2->setStyleSheet("* {background-color: white; min-width: 250px; max-width:500px }");
1029 tabWidget.addTab(page2,"Tab2");
1030 QWidget *page3=new QLabel("plop");
1031 page3->setObjectName("Page3");
1032 page3->setStyleSheet("* {background-color: yellow; min-height: 250px; max-height:500px }");
1033 int index3 = tabWidget.addTab(page3,"very_long_long_long_long_caption");
1035 tabWidget.setStyleSheet("QTabBar::tab { min-width:100px; max-width:130px; }");
1039 //i allow 4px additional border from the native style (hence the -2, <=2)
1040 QVERIFY(qAbs(page2->maximumSize().width() - 500 - 2) <= 2);
1041 QVERIFY(qAbs(page2->minimumSize().width() - 250 - 2) <= 2);
1042 QVERIFY(qAbs(page3->maximumSize().height() - 500 - 2) <= 2);
1043 QVERIFY(qAbs(page3->minimumSize().height() - 250 - 2) <= 2);
1044 QVERIFY(qAbs(page3->minimumSize().height() - 250 - 2) <= 2);
1045 QTabBar *bar = qFindChild<QTabBar*>(&tabWidget);
1048 QEXPECT_FAIL("", "QTBUG-23686", Continue);
1050 QVERIFY(qAbs(bar->tabRect(index1).width() - 100 - 2) <= 2);
1052 QEXPECT_FAIL("", "QTBUG-23686", Continue);
1054 QVERIFY(qAbs(bar->tabRect(index3).width() - 130 - 2) <= 2);
1057 void tst_QStyleSheetStyle::task206238_twice()
1060 QTabWidget* tw = new QTabWidget;
1061 tw->addTab(new QLabel("foo"), "test");
1062 w.setCentralWidget(tw);
1063 w.setStyleSheet("background: red;");
1066 QCOMPARE(BACKGROUND(w) , QColor("red"));
1067 QCOMPARE(BACKGROUND(*tw), QColor("red"));
1068 w.setStyleSheet("background: red;");
1070 QCOMPARE(BACKGROUND(w) , QColor("red"));
1071 QCOMPARE(BACKGROUND(*tw), QColor("red"));
1074 void tst_QStyleSheetStyle::transparent()
1077 QPushButton *p1=new QPushButton(&w);
1078 QPushButton *p2=new QPushButton(&w);
1079 QPushButton *p3=new QPushButton(&w);
1080 p1->setStyleSheet("background:transparent");
1081 p2->setStyleSheet("background-color:transparent");
1082 p3->setStyleSheet("background:rgb(0,0,0,0)");
1083 QCOMPARE(BACKGROUND(*p1) , QColor(0,0,0,0));
1084 QCOMPARE(BACKGROUND(*p2) , QColor(0,0,0,0));
1085 QCOMPARE(BACKGROUND(*p3) , QColor(0,0,0,0));
1090 class ProxyStyle : public QStyle
1093 ProxyStyle(QStyle *s)
1098 void drawControl(ControlElement ce, const QStyleOption *opt,
1099 QPainter *painter, const QWidget *widget = 0) const;
1101 void drawPrimitive(QStyle::PrimitiveElement pe,
1102 const QStyleOption* opt,
1104 const QWidget* w) const
1106 style->drawPrimitive(pe, opt, p, w);
1109 QRect subElementRect(QStyle::SubElement se,
1110 const QStyleOption* opt,
1111 const QWidget* w) const
1116 return QRect(0, 0, 3, 3);
1119 void drawComplexControl(QStyle::ComplexControl cc,
1120 const QStyleOptionComplex* opt,
1122 const QWidget* w) const
1124 style->drawComplexControl(cc, opt, p, w);
1128 SubControl hitTestComplexControl(QStyle::ComplexControl cc,
1129 const QStyleOptionComplex* opt,
1131 const QWidget* w) const
1133 return style->hitTestComplexControl(cc, opt, pt, w);
1136 QRect subControlRect(QStyle::ComplexControl cc,
1137 const QStyleOptionComplex* opt,
1138 QStyle::SubControl sc,
1139 const QWidget* w) const
1141 return style->subControlRect(cc, opt, sc, w);
1144 int pixelMetric(QStyle::PixelMetric pm,
1145 const QStyleOption* opt,
1146 const QWidget* w) const
1148 return style->pixelMetric(pm, opt, w);
1152 QSize sizeFromContents(QStyle::ContentsType ct,
1153 const QStyleOption* opt,
1155 const QWidget* w) const
1157 return style->sizeFromContents(ct, opt, size, w);
1160 int styleHint(QStyle::StyleHint sh,
1161 const QStyleOption* opt,
1163 QStyleHintReturn* shr) const
1165 return style->styleHint(sh, opt, w, shr);
1168 QPixmap standardPixmap(QStyle::StandardPixmap spix,
1169 const QStyleOption* opt,
1170 const QWidget* w) const
1172 return style->standardPixmap(spix, opt, w);
1175 QPixmap generatedIconPixmap(QIcon::Mode mode,
1177 const QStyleOption* opt) const
1179 return style->generatedIconPixmap(mode, pix, opt);
1186 void ProxyStyle::drawControl(ControlElement ce, const QStyleOption *opt,
1187 QPainter *painter, const QWidget *widget) const
1189 if(ce == CE_PushButton)
1191 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt))
1193 QRect r = btn->rect;
1194 painter->fillRect(r, Qt::green);
1196 if(btn->state & QStyle::State_HasFocus)
1197 painter->fillRect(r.adjusted(5, 5, -5, -5), Qt::yellow);
1200 painter->drawText(r, Qt::AlignCenter, btn->text);
1205 style->drawControl(ce, opt, painter, widget);
1209 void tst_QStyleSheetStyle::proxyStyle()
1211 //Should not crash; task 158984
1213 ProxyStyle *proxy = new ProxyStyle(qApp->style());
1214 QString styleSheet("QPushButton {background-color: red; }");
1216 QWidget *w = new QWidget;
1217 QVBoxLayout *layout = new QVBoxLayout(w);
1219 QPushButton *pb1 = new QPushButton(qApp->style()->objectName(), w);
1220 layout->addWidget(pb1);
1222 QPushButton *pb2 = new QPushButton("ProxyStyle", w);
1223 pb2->setStyle(proxy);
1224 layout->addWidget(pb2);
1226 QPushButton *pb3 = new QPushButton("StyleSheet", w);
1227 pb3->setStyleSheet(styleSheet);
1228 layout->addWidget(pb3);
1230 QPushButton *pb4 = new QPushButton("StyleSheet then ProxyStyle ", w);
1231 pb4->setStyleSheet(styleSheet);
1233 // We are creating our Proxy based on current style...
1234 // In this case it would be the QStyleSheetStyle that is deleted
1235 // later on. We need to get access to the "real" QStyle to be able to
1237 ProxyStyle* newProxy = new ProxyStyle(qApp->style());
1238 pb4->setStyle(newProxy);
1240 layout->addWidget(pb4);
1242 QPushButton *pb5 = new QPushButton("ProxyStyle then StyleSheet ", w);
1243 pb5->setStyle(proxy);
1244 pb5->setStyleSheet(styleSheet);
1245 layout->addWidget(pb5);
1251 // Test for QTBUG-7198 - style sheet overrides custom element size
1252 QStyleOptionViewItemV4 opt;
1254 opt.features |= QStyleOptionViewItemV2::HasCheckIndicator;
1255 QVERIFY(pb5->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator,
1256 &opt, pb5).width() == 3);
1262 void tst_QStyleSheetStyle::dialogButtonBox()
1264 QDialogButtonBox box;
1265 box.addButton(QDialogButtonBox::Ok);
1266 box.addButton(QDialogButtonBox::Cancel);
1267 box.setStyleSheet("/** */ ");
1268 box.setStyleSheet(QString()); //should not crash
1271 void tst_QStyleSheetStyle::emptyStyleSheet()
1273 //empty stylesheet should not change anything
1274 qApp->setStyleSheet(QString());
1276 QHBoxLayout layout(&w);
1277 w.setLayout(&layout);
1278 layout.addWidget(new QPushButton("push", &w));
1279 layout.addWidget(new QToolButton(&w));
1280 QLabel label("toto", &w);
1281 label.setFrameShape(QLabel::Panel);
1282 label.setFrameShadow(QLabel::Sunken);
1283 layout.addWidget(&label); //task 231137
1284 layout.addWidget(new QTableWidget(200,200, &w));
1285 layout.addWidget(new QProgressBar(&w));
1286 layout.addWidget(new QLineEdit(&w));
1287 layout.addWidget(new QSpinBox(&w));
1288 layout.addWidget(new QComboBox(&w));
1289 layout.addWidget(new QDateEdit(&w));
1290 layout.addWidget(new QGroupBox("some text", &w));
1293 QVERIFY(QTest::qWaitForWindowExposed(&w));
1294 //workaround the fact that the label sizehint is one pixel different the first time.
1295 label.setIndent(0); //force to recompute the sizeHint:
1299 QImage img1(w.size(), QImage::Format_ARGB32);
1302 w.setStyleSheet("/* */");
1305 QImage img2(w.size(), QImage::Format_ARGB32);
1309 img1.save("emptyStyleSheet_img1.png");
1310 img2.save("emptyStyleSheet_img2.png");
1313 QCOMPARE(img1,img2);
1316 void tst_QStyleSheetStyle::toolTip()
1318 qApp->setStyleSheet(QString());
1320 QHBoxLayout layout(&w);
1321 w.setLayout(&layout);
1323 QWidget *wid1 = new QGroupBox(&w);
1324 layout.addWidget(wid1);
1325 wid1->setStyleSheet("QToolTip { background: #ae2; } #wid3 > QToolTip { background: #0b8; } ");
1326 QVBoxLayout *layout1 = new QVBoxLayout(wid1);
1327 wid1->setLayout(layout1);
1328 wid1->setToolTip("this is wid1");
1329 wid1->setObjectName("wid1");
1331 QWidget *wid2 = new QPushButton("wid2", wid1);
1332 layout1->addWidget(wid2);
1333 wid2->setStyleSheet("QToolTip { background: #f81; } ");
1334 wid2->setToolTip("this is wid2");
1335 wid2->setObjectName("wid2");
1337 QWidget *wid3 = new QPushButton("wid3", wid1);
1338 layout1->addWidget(wid3);
1339 wid3->setToolTip("this is wid3");
1340 wid3->setObjectName("wid3");
1342 QWidget *wid4 = new QPushButton("wid4", &w);
1343 layout.addWidget(wid4);
1344 wid4->setToolTip("this is wid4");
1345 wid4->setObjectName("wid4");
1348 qApp->setActiveWindow(&w);
1349 QVERIFY(QTest::qWaitForWindowActive(&w));
1351 QColor normalToolTip = qApp->palette().toolTipBase().color();
1352 QList<QWidget *> widgets;
1353 QList<QColor> colors;
1356 //tooltip on the widget without stylesheet, then to othes widget, including one without stylesheet
1357 //(the tooltip will be reused but his colour must change)
1358 widgets << wid4 << wid1 << wid2 << wid3 << wid4;
1359 colors << normalToolTip << "#ae2" << "#f81" << "#0b8" << normalToolTip;
1361 for (int i = 0; i < widgets.count() ; i++)
1363 QWidget *wid = widgets.at(i);
1364 QColor col = colors.at(i);
1366 QToolTip::showText( QPoint(0,0) , "This is " + wid->objectName(), wid);
1368 QWidget *tooltip = 0;
1369 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1370 if (widget->inherits("QTipLabel") && widget->isVisible()) {
1376 QCOMPARE(tooltip->palette().color(tooltip->backgroundRole()), col);
1379 QToolTip::showText( QPoint(0,0) , "This is " + wid3->objectName(), wid3);
1381 delete wid3; //should not crash;
1383 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1384 widget->update(); //should not crash either
1388 void tst_QStyleSheetStyle::embeddedFonts()
1390 //task 235622 and 210551
1393 spin.setStyleSheet("QSpinBox { font-size: 32px; }");
1395 QLineEdit *embedded = spin.findChild<QLineEdit *>();
1397 QCOMPARE(spin.font().pixelSize(), 32);
1398 QCOMPARE(embedded->font().pixelSize(), 32);
1400 QMenu *menu = embedded->createStandardContextMenu();
1404 QVERIFY(menu->font().pixelSize() != 32);
1405 QCOMPARE(menu->font().pixelSize(), qApp->font(menu).pixelSize());
1409 box.setEditable(true);
1410 box.addItems(QStringList() << "First" << "Second" << "Third");
1411 box.setStyleSheet("QComboBox { font-size: 32px; }");
1413 embedded = box.findChild<QLineEdit *>();
1416 QCOMPARE(box.font().pixelSize(), 32);
1417 QCOMPARE(embedded->font().pixelSize(), 32);
1420 void tst_QStyleSheetStyle::opaquePaintEvent_data()
1422 QTest::addColumn<QString>("stylesheet");
1423 QTest::addColumn<bool>("transparent");
1424 QTest::addColumn<bool>("styled");
1426 QTest::newRow("none") << QString::fromLatin1("/* */") << false << false;
1427 QTest::newRow("background black ") << QString::fromLatin1("background: black;") << false << true;
1428 QTest::newRow("background qrgba") << QString::fromLatin1("background: rgba(125,0,0,125);") << true << true;
1429 QTest::newRow("background transparent") << QString::fromLatin1("background: transparent;") << true << true;
1430 QTest::newRow("border native") << QString::fromLatin1("border: native;") << false << false;
1431 QTest::newRow("border solid") << QString::fromLatin1("border: 2px solid black;") << true << true;
1432 QTest::newRow("border transparent") << QString::fromLatin1("background: black; border: 2px solid rgba(125,0,0,125);") << true << true;
1433 QTest::newRow("margin") << QString::fromLatin1("margin: 25px;") << true << true;
1434 QTest::newRow("focus") << QString::fromLatin1("*:focus { background: rgba(125,0,0,125) }") << true << true;
1437 void tst_QStyleSheetStyle::opaquePaintEvent()
1439 QFETCH(QString, stylesheet);
1440 QFETCH(bool, transparent);
1441 QFETCH(bool, styled);
1445 cl.setAttribute(Qt::WA_OpaquePaintEvent, true);
1446 cl.setAutoFillBackground(true);
1447 cl.setStyleSheet(stylesheet);
1448 cl.ensurePolished();
1449 QCOMPARE(cl.testAttribute(Qt::WA_OpaquePaintEvent), !transparent);
1450 QCOMPARE(cl.testAttribute(Qt::WA_StyledBackground), styled);
1451 QCOMPARE(cl.autoFillBackground(), !styled );
1454 void tst_QStyleSheetStyle::complexWidgetFocus()
1456 // This test is a simplified version of the focusColors() test above.
1458 // Tests if colors can be changed by altering the focus of the widget.
1459 // To avoid messy pixel-by-pixel comparison, we assume that the goal
1460 // is reached if at least ten pixels of the right color can be found in
1462 // For this reason, we use unusual and extremely ugly colors! :-)
1465 frame.setStyleSheet("*:focus { background: black; color: black } "
1466 "QSpinBox::up-arrow:focus, QSpinBox::down-arrow:focus { width: 7px; height: 7px; background: #ff0084 } "
1467 "QComboBox::down-arrow:focus { width: 7px; height: 7px; background: #ff0084 }"
1468 "QSlider::handle:horizontal:focus { width: 7px; height: 7px; background: #ff0084 } ");
1470 QList<QWidget *> widgets;
1471 widgets << new QSpinBox;
1472 widgets << new QComboBox;
1473 widgets << new QSlider(Qt::Horizontal);
1475 QLayout* layout = new QGridLayout;
1476 layout->addWidget(new QLineEdit); // Avoids initial focus.
1477 foreach (QWidget *widget, widgets)
1478 layout->addWidget(widget);
1479 frame.setLayout(layout);
1482 QApplication::setActiveWindow(&frame);
1483 QVERIFY(QTest::qWaitForWindowActive(&frame));
1484 foreach (QWidget *widget, widgets) {
1486 QApplication::processEvents();
1488 QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
1489 frame.render(&image);
1490 if (image.depth() < 24)
1491 QSKIP("Test doesn't support color depth < 24");
1493 QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
1494 (QString::fromLatin1(widget->metaObject()->className())
1495 + " did not contain text color #ff0084, using style "
1496 + QString::fromLatin1(qApp->style()->metaObject()->className()))
1497 .toLocal8Bit().constData());
1501 void tst_QStyleSheetStyle::task188195_baseBackground()
1504 tree.setStyleSheet( "QTreeView:disabled { background-color:#ab1251; }" );
1507 QImage image(tree.width(), tree.height(), QImage::Format_ARGB32);
1509 tree.render(&image);
1510 QVERIFY(testForColors(image, tree.palette().base().color()));
1511 QVERIFY(!testForColors(image, QColor(0xab, 0x12, 0x51)));
1513 tree.setEnabled(false);
1514 tree.render(&image);
1515 QVERIFY(testForColors(image, QColor(0xab, 0x12, 0x51)));
1517 tree.setEnabled(true);
1518 tree.render(&image);
1519 QVERIFY(testForColors(image, tree.palette().base().color()));
1520 QVERIFY(!testForColors(image, QColor(0xab, 0x12, 0x51)));
1522 QTableWidget table(12, 12);
1523 table.setItem(0, 0, new QTableWidgetItem());
1524 table.setStyleSheet( "QTableView {background-color: #ff0000}" );
1527 image = QImage(table.width(), table.height(), QImage::Format_ARGB32);
1528 table.render(&image);
1529 QVERIFY(testForColors(image, Qt::red, true));
1532 void tst_QStyleSheetStyle::task232085_spinBoxLineEditBg()
1534 // This test is a simplified version of the focusColors() test above.
1536 // Tests if colors can be changed by altering the focus of the widget.
1537 // To avoid messy pixel-by-pixel comparison, we assume that the goal
1538 // is reached if at least ten pixels of the right color can be found in
1540 // For this reason, we use unusual and extremely ugly colors! :-)
1542 QSpinBox *spinbox = new QSpinBox;
1543 spinbox->setValue(8888);
1546 QLayout* layout = new QGridLayout;
1548 QLineEdit* dummy = new QLineEdit; // Avoids initial focus.
1550 // We only want to test the line edit colors.
1551 spinbox->setStyleSheet("QSpinBox:focus { background: #e8ff66; color: #ff0084 } "
1552 "QSpinBox::up-button, QSpinBox::down-button { background: black; }");
1554 layout->addWidget(dummy);
1555 layout->addWidget(spinbox);
1556 frame.setLayout(layout);
1559 QApplication::setActiveWindow(&frame);
1560 spinbox->setFocus();
1561 QVERIFY(QTest::qWaitForWindowActive(&frame));
1563 QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
1564 frame.render(&image);
1565 if (image.depth() < 24)
1566 QSKIP("Test doesn't support color depth < 24");
1568 QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
1569 (QString::fromLatin1(spinbox->metaObject()->className())
1570 + " did not contain background color #e8ff66, using style "
1571 + QString::fromLatin1(qApp->style()->metaObject()->className()))
1572 .toLocal8Bit().constData());
1573 QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
1574 (QString::fromLatin1(spinbox->metaObject()->className())
1575 + " did not contain text color #ff0084, using style "
1576 + QString::fromLatin1(qApp->style()->metaObject()->className()))
1577 .toLocal8Bit().constData());
1580 class ChangeEventWidget : public QWidget
1582 void changeEvent(QEvent * event)
1584 if(event->type() == QEvent::StyleChange) {
1585 static bool recurse = false;
1588 QStyle *style = new QMotifStyle;
1589 style->setParent(this);
1594 QWidget::changeEvent(event);
1598 void tst_QStyleSheetStyle::changeStyleInChangeEvent()
1600 ChangeEventWidget wid;
1601 wid.ensurePolished();
1602 wid.setStyleSheet(" /* */ ");
1603 wid.ensurePolished();
1604 wid.setStyleSheet(" /* ** */ ");
1605 wid.ensurePolished();
1608 void tst_QStyleSheetStyle::QTBUG11658_cachecrash()
1611 class Widget : public QWidget
1614 Widget(QWidget *parent = 0)
1617 QVBoxLayout* pLayout = new QVBoxLayout(this);
1618 QCheckBox* pCheckBox = new QCheckBox(this);
1619 pLayout->addWidget(pCheckBox);
1622 QString szStyleSheet = QLatin1String("* { color: red; }");
1623 qApp->setStyleSheet(szStyleSheet);
1624 qApp->setStyle(QStyleFactory::create(QLatin1String("Windows")));
1628 Widget *w = new Widget();
1633 QVERIFY(QTest::qWaitForWindowExposed(w));
1635 qApp->setStyleSheet(QString());
1638 void tst_QStyleSheetStyle::QTBUG15910_crashNullWidget()
1640 struct Widget : QWidget {
1641 virtual void paintEvent(QPaintEvent* ) {
1645 style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, 0);
1646 style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, 0);
1647 style()->drawControl(QStyle::CE_PushButton, &opt, &p, 0);
1650 w.setStyleSheet("* { background-color: white; color:black; border 3px solid yellow }");
1652 QVERIFY(QTest::qWaitForWindowExposed(&w));
1656 QTEST_MAIN(tst_QStyleSheetStyle)
1657 #include "tst_qstylesheetstyle.moc"