QtBase  v6.3.1
tst_qmacstyle.cpp
Go to the documentation of this file.
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 
30 #include <QTest>
31 #include <QtWidgets>
32 #include <private/qstylehelper_p.h>
33 
35 
36 #define CT(E) \
37  static const ControlType E = QSizePolicy::E;
38 
40 
41 CT(ButtonBox)
42 CT(CheckBox)
43 CT(ComboBox)
44 CT(Label)
45 CT(LineEdit)
46 CT(PushButton)
47 CT(RadioButton)
48 
49 class tst_QMacStyle : public QObject
50 {
51  Q_OBJECT
52 
53 public:
54  tst_QMacStyle() { qRegisterMetaType<QStyleHelper::WidgetSizePolicy>("WidgetSizePolicy"); }
55 
56 private slots:
57  void sizeHints_data();
58  void sizeHints();
59  void layoutMargins_data();
60  void layoutMargins();
61  void layoutSpacings_data();
62  void layoutSpacings();
63  void smallMiniNormalExclusivity_data();
64  void smallMiniNormalExclusivity();
65  void passwordCharacter();
66 
67 private:
68  static QSize msh(QWidget *widget);
69  static QSize sh(QWidget *widget);
70  static QRect geo(QWidget *widget);
71  static QPoint pos(QWidget *widget) { return geo(widget).topLeft(); }
72  static QSize size(QWidget *widget) { return geo(widget).size(); }
73  static QSize gap(QWidget *widget1, QWidget *widget2);
74  static int hgap(QWidget *widget1, QWidget *widget2) { return gap(widget1, widget2).width(); }
75  static int vgap(QWidget *widget1, QWidget *widget2) { return gap(widget1, widget2).height(); }
76  static void setSize(QWidget *widget, QStyleHelper::WidgetSizePolicy size);
77  static int spacing(ControlType control1, ControlType control2, Qt::Orientation orientation,
78  QStyleOption *option = nullptr, QWidget *widget = nullptr);
79  static int hspacing(ControlType control1, ControlType control2, QStyleHelper::WidgetSizePolicy size = QStyleHelper::SizeLarge);
80  static int vspacing(ControlType control1, ControlType control2, QStyleHelper::WidgetSizePolicy size = QStyleHelper::SizeLarge);
81 };
82 
83 #define SIZE(x, y, z) \
84  ((size == QStyleHelper::SizeLarge) ? (x) : (size == QStyleHelper::SizeSmall) ? (y) : (z))
85 
86 static bool bigSurOrAbove() {
88 }
89 
90 void tst_QMacStyle::sizeHints_data()
91 {
92  QTest::addColumn<QStyleHelper::WidgetSizePolicy>("size");
94 // QTest::newRow("small") << QStyleHelper::SizeSmall;
95 // QTest::newRow("mini") << QStyleHelper::SizeMini;
96 }
97 
98 void tst_QMacStyle::sizeHints()
99 {
101  QDialog w;
102  setSize(&w, size);
103 
104  QLineEdit lineEdit1(&w);
105  QCOMPARE(sh(&lineEdit1).height(), SIZE(21, 19, 16)); // 16 in Builder, 15 in AHIG
106 
107  QProgressBar progress1(&w);
108  progress1.setOrientation(Qt::Horizontal);
109  qDebug() << "sh" << progress1.sizeHint();
110  QCOMPARE(sh(&progress1).height(), SIZE(16, 10, 10)); // Builder
111 
112  progress1.setOrientation(Qt::Vertical);
113  QCOMPARE(sh(&progress1).width(), SIZE(16, 10, 10)); // Builder
114 
115  QRadioButton radio1("Radio", &w);
116  QCOMPARE(sh(&radio1).height(), SIZE(14, 12, 10)); // Builder
117 
118  QCheckBox checkBox1("Switch", &w);
119  QCOMPARE(sh(&checkBox1).height(), SIZE(13, 12, 10)); // Builder
120 
121  QComboBox comboBox1(&w);
122  comboBox1.setEditable(false);
123  comboBox1.addItem("Foo");
124  QCOMPARE(sh(&comboBox1).height(), SIZE(26, 17, 15));
125 
126  QComboBox comboBox2(&w);
127  comboBox2.setEditable(true);
128  comboBox2.addItem("Foo");
129  QCOMPARE(sh(&comboBox2).height(), SIZE(26, 17, 15));
130 
131  // Combos in toolbars use the actual widget rect to
132  // avoid faulty clipping:
133  QToolBar tb;
134  setSize(&tb, size);
135  QComboBox comboBox3(&tb);
136  comboBox3.addItem("Foo");
137  QCOMPARE(sh(&comboBox3).height(), SIZE(32, -1, -1));
138 
139  QSlider slider1(Qt::Horizontal, &w);
140  QCOMPARE(sh(&slider1).height(), SIZE(bigSurOrAbove() ? 18 : 15, 12, 10));
141 
142  slider1.setTickPosition(QSlider::TicksAbove);
143  QCOMPARE(sh(&slider1).height(), SIZE(24, 17, 16)); // Builder
144 
145  slider1.setTickPosition(QSlider::TicksBelow);
146  QCOMPARE(sh(&slider1).height(), SIZE(24, 17, 16)); // Builder
147 
148  slider1.setTickPosition(QSlider::TicksBothSides);
149  QVERIFY(sh(&slider1).height() > SIZE(bigSurOrAbove() ? 18 : 15, 12, 10)); // common sense
150 
151  QPushButton ok1("OK", &w);
152  QPushButton cancel1("Cancel", &w);
153 
154  QSize s1 = sh(&ok1);
155  if (size == QStyleHelper::SizeLarge) {
156  // AHIG says 68, Builder does 70, and Qt seems to do 69
157  QVERIFY(s1.width() >= 68 && s1.width() <= 70);
158  }
159  QCOMPARE(s1.height(), SIZE(20, 17, 14)); // 14 in Builder, 15 in AHIG
160 
161  // Cancel should be identical to OK, no matter what
162  QCOMPARE(s1, sh(&cancel1));
163 
164  // Play with auto-default and default
165  cancel1.setAutoDefault(false);
166  QCOMPARE(s1, sh(&cancel1));
167  cancel1.setAutoDefault(true);
168  QCOMPARE(s1, sh(&cancel1));
169  cancel1.setDefault(true);
170  QCOMPARE(s1, sh(&cancel1));
171 
173  bbox.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
174  QCOMPARE(s1, sh(bbox.button(QDialogButtonBox::Ok)));
176 
177  QMessageBox mbox(&w);
178  mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
179  QCOMPARE(s1, sh(mbox.button(QMessageBox::Ok)));
180  QCOMPARE(s1, sh(mbox.button(QMessageBox::Cancel)));
181 
182  /*
183  QSpinBox spinBox1(&w);
184  int h1 = sh(&spinBox1).height();
185  QCOMPARE(h1, SIZE(22, 19, 15));
186 
187  QDateEdit date1(&w);
188  QCOMPARE(sh(&date1).height(), h1);
189 
190  QTimeEdit time1(&w);
191  QCOMPARE(sh(&time1).height(), h1);
192 
193  QDateTimeEdit dateTime1(&w);
194  QCOMPARE(sh(&dateTime1).height(), h1);
195 
196  QSize s2 = sh(&ok1);
197  if (size == Normal) {
198  QVERIFY(s2.height() >= 21 && s2.height() <= 32);
199  } else {
200  QVERIFY(s2.height() >= 18 && s2.height() <= 24);
201  }
202  */
203 
204  // QMacStyle bug: label doesn't react to Small and Mini
205  QLabel label1("Blah", &w);
206  QCOMPARE(sh(&label1).height(), SIZE(16, 14, 11));
207 }
208 
209 void tst_QMacStyle::layoutMargins_data()
210 {
211  tst_QMacStyle::sizeHints_data();
212 }
213 
214 void tst_QMacStyle::layoutMargins()
215 {
217  QWidget w;
218  setSize(&w, size);
219 
220 }
221 
222 void tst_QMacStyle::layoutSpacings_data()
223 {
224  tst_QMacStyle::sizeHints_data();
225 }
226 
227 void tst_QMacStyle::layoutSpacings()
228 {
230 
231  /*
232  Constraints specified by AHIG.
233  */
234 
235  for (int i = 0; i < 4; ++i) {
236  ControlType c1 = (i % 2 == 0) ? PushButton : ButtonBox;
237  ControlType c2 = (i / 2 == 0) ? PushButton : ButtonBox;
238  QCOMPARE(hspacing(c1, c2, size), SIZE(14, 8, 8));
239  QCOMPARE(vspacing(c1, c2, size), SIZE(14, 8, 8));
240  }
241 
242  QCOMPARE(hspacing(Label, RadioButton, size), SIZE(8, 6, 5));
243  QCOMPARE(vspacing(RadioButton, RadioButton, size), SIZE(5, 5, 5)); // Builder, guess, AHIG
244 
245  QCOMPARE(hspacing(Label, CheckBox, size), SIZE(8, 6, 5));
246  QCOMPARE(vspacing(CheckBox, CheckBox, size), SIZE(8, 8, 7));
247 
248  QCOMPARE(hspacing(Label, ComboBox, size), SIZE(8, 6, 5));
249 
250  QCOMPARE(hspacing(LineEdit, LineEdit, size), SIZE(10, 8, 8));
251 
252  /*
253  Common sense constraints, for when AHIG seems to make no sense (e.g., disagrees
254  too much with Builder or looks improper).
255  */
256 
257  // Comboboxes are a special pain, because AHIG and Builder can't agree,
258  // and because they can be editable or not, with two totally different looks
259  QVERIFY(vspacing(ComboBox, ComboBox, size) >= SIZE(8, 6, 5));
260  QVERIFY(vspacing(ComboBox, ComboBox, size) <= SIZE(12, 10, 8));
261 
262  // Make sure button boxes get the respect they deserve, when they occur
263  // in the bottom or right side of a dialog
264  QCOMPARE(hspacing(ButtonBox, LineEdit), SIZE(20, 8, 8));
265  QCOMPARE(vspacing(ButtonBox, LineEdit), SIZE(20, 7, 7));
266 
267  QCOMPARE(hspacing(LineEdit, ButtonBox), SIZE(8, 8, 8));
268  QCOMPARE(vspacing(LineEdit, ButtonBox), SIZE(8, 8, 8));
269 }
270 
271 // helper functions
272 
273 QSize tst_QMacStyle::msh(QWidget *widget)
274 {
276  return item.sizeHint();
277 }
278 
279 QSize tst_QMacStyle::sh(QWidget *widget)
280 {
282  return item.sizeHint();
283 }
284 
285 QRect tst_QMacStyle::geo(QWidget *widget)
286 {
288  return item.geometry();
289 }
290 
291 QSize tst_QMacStyle::gap(QWidget *widget1, QWidget *widget2)
292 {
293  QPoint d = pos(widget2) - pos(widget1);
294  QSize s = size(widget1);
295  return s + QSize(d.x(), d.y());
296 }
297 
298 void tst_QMacStyle::setSize(QWidget *widget, QStyleHelper::WidgetSizePolicy size)
299 {
300  switch (size) {
302  break;
305  break;
308  break;
311  }
312 }
313 
314 int tst_QMacStyle::spacing(ControlType control1, ControlType control2, Qt::Orientation orientation,
316 {
317  return QApplication::style()->layoutSpacing(control1, control2, orientation, option, widget);
318 }
319 
320 int tst_QMacStyle::hspacing(ControlType control1, ControlType control2, QStyleHelper::WidgetSizePolicy size)
321 {
322  QWidget w;
323  setSize(&w, size);
324 
326  opt.initFrom(&w);
327 
328  return spacing(control1, control2, Qt::Horizontal, &opt);
329 }
330 
331 int tst_QMacStyle::vspacing(ControlType control1, ControlType control2, QStyleHelper::WidgetSizePolicy size)
332 {
333  QWidget w;
334  setSize(&w, size);
335 
337  opt.initFrom(&w);
338 
339  return spacing(control1, control2, Qt::Vertical, &opt);
340 }
341 
342 
343 void tst_QMacStyle::smallMiniNormalExclusivity_data()
344 {
345 
346  QTest::addColumn<int>("size1");
347  QTest::addColumn<int>("size2");
348  QTest::addColumn<int>("size3");
349  QTest::addColumn<int>("expectedHeight1");
350  QTest::addColumn<int>("expectedHeight2");
351  QTest::addColumn<int>("expectedHeight3");
352 
353  QTest::newRow("normal small mini") << int(Qt::WA_MacNormalSize) << int(Qt::WA_MacSmallSize) << int(Qt::WA_MacMiniSize) << 32 << 16 << 24;
354  QTest::newRow("normal mini small") << int(Qt::WA_MacNormalSize) <<int(Qt::WA_MacMiniSize) << int(Qt::WA_MacSmallSize) << 32 << 24 << 16;
355  QTest::newRow("small normal mini") << int(Qt::WA_MacSmallSize) << int(Qt::WA_MacNormalSize) << int(Qt::WA_MacMiniSize) << 16 << 32 << 24;
356  QTest::newRow("small mini normal") << int(Qt::WA_MacSmallSize) << int(Qt::WA_MacMiniSize) << int(Qt::WA_MacNormalSize) << 16 << 24 << 32;
357  QTest::newRow("mini small normal") << int(Qt::WA_MacMiniSize) << int(Qt::WA_MacSmallSize) << int(Qt::WA_MacNormalSize) << 24 << 16 << 32;
358  QTest::newRow("mini normal small") << int(Qt::WA_MacMiniSize) << int(Qt::WA_MacNormalSize) << int(Qt::WA_MacSmallSize) << 24 << 32 << 16;
359 }
360 
361 void tst_QMacStyle::smallMiniNormalExclusivity()
362 {
363 
364  QFETCH(int, size1);
365  QFETCH(int, size2);
366  QFETCH(int, size3);
367  QFETCH(int, expectedHeight1);
368  QFETCH(int, expectedHeight2);
369  QFETCH(int, expectedHeight3);
370 
371  static const int TotalSizes = 3;
372  int attrs[TotalSizes] = { size1, size2, size3 };
373  int expected[TotalSizes] = { expectedHeight1, expectedHeight2, expectedHeight3 };
374 
375  QPushButton dummyWidget;
377 
378  for (int i = 0; i < TotalSizes; ++i) {
379  dummyWidget.setAttribute(Qt::WidgetAttribute(attrs[i]));
380  opt.initFrom(&dummyWidget);
382  QSize(0, 0), &dummyWidget);
383  if (size.height() != expected[i])
384  QEXPECT_FAIL("", "QTBUG-25296", Abort);
385  QCOMPARE(size.height(), expected[i]);
386  }
387 }
388 
389 void tst_QMacStyle::passwordCharacter()
390 {
393  QTest::keyClick(&lineEdit, Qt::Key_P);
394  // Should be no password delay; text should instantly be masked.
395  const QChar bullet(0x2022);
396  const QString expected(1, bullet);
397  QCOMPARE(lineEdit.displayText(), expected);
398 }
399 
401 #include "tst_qmacstyle.moc"
402 
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
Definition: label.h:39
static QStyle * style()
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:84
The QCheckBox widget provides a checkbox with a text label.
Definition: qcheckbox.h:55
The QComboBox widget is a combined button and popup list.
Definition: qcombobox.h:60
The QDialogButtonBox class is a widget that presents buttons in a layout that is appropriate to the c...
The QDialog class is the base class of dialog windows.
Definition: qdialog.h:55
The QLabel widget provides a text or image display.
Definition: qlabel.h:56
The QLineEdit widget is a one-line text editor.
Definition: qlineedit.h:64
QString displayText
the displayed text.
Definition: qlineedit.h:72
void setEchoMode(EchoMode)
Definition: qlineedit.cpp:572
The QMessageBox class provides a modal dialog for informing the user or for asking the user a questio...
Definition: qmessagebox.h:57
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
static QOperatingSystemVersion current()
[0]
static constexpr QOperatingSystemVersionBase MacOSBigSur
a version corresponding to macOS Big Sur
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:52
The QProgressBar widget provides a horizontal or vertical progress bar.
Definition: qprogressbar.h:54
The QPushButton widget provides a command button.
Definition: qpushbutton.h:56
The QRadioButton widget provides a radio button with a text label.
Definition: qradiobutton.h:55
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:59
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
The QSlider widget provides a vertical or horizontal slider.
Definition: qslider.h:54
@ TicksAbove
Definition: qslider.h:63
@ TicksBelow
Definition: qslider.h:65
@ TicksBothSides
Definition: qslider.h:67
The QString class provides a Unicode character string.
Definition: qstring.h:388
@ CT_PushButton
Definition: qstyle.h:581
virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w=nullptr) const =0
virtual int layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
where ellipsis should be added for text that is too long to fit into an item
Definition: qstyleoption.h:251
The QStyleOption class stores the parameters used by QStyle functions.
Definition: qstyleoption.h:75
void initFrom(const QWidget *w)
The QToolBar class provides a movable panel that contains a set of controls.
Definition: qtoolbar.h:59
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:133
void setAttribute(Qt::WidgetAttribute, bool on=true)
Definition: qwidget.cpp:11088
QStyle * style() const
Definition: qwidget.cpp:2612
The QWidgetItem class is a layout item that represents a widget.
Definition: qlayoutitem.h:122
QOpenGLWidget * widget
[1]
qreal spacing
QCOMPARE(spy.count(), 1)
QStyleOptionButton opt
FT_BBox bbox
Definition: ftbbox.c:467
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
WidgetAttribute
Definition: qnamespace.h:307
@ WA_MacMiniSize
Definition: qnamespace.h:388
@ WA_MacNormalSize
Definition: qnamespace.h:386
@ WA_MacSmallSize
Definition: qnamespace.h:387
Orientation
Definition: qnamespace.h:123
@ Horizontal
Definition: qnamespace.h:124
@ Vertical
Definition: qnamespace.h:125
@ Key_P
Definition: qnamespace.h:587
#define qDebug
[1]
Definition: qlogging.h:177
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLint GLsizei width
GLdouble s
[6]
Definition: qopenglext.h:235
GLuint GLenum option
Definition: qopenglext.h:5929
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QEXPECT_FAIL(dataIndex, comment, mode)
Definition: qtestcase.h:224
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
QLineEdit * lineEdit
MyCustomStruct c2
QGraphicsItem * item
QSizePolicy::ControlType ControlType
#define CT(E)
Q_DECLARE_METATYPE(QStyleHelper::WidgetSizePolicy)
#define SIZE(x, y, z)