Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qgroupbox.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qgroupbox.h"
5
6#include "qapplication.h"
7#include "qbitmap.h"
8#include "qdrawutil.h"
9#include "qevent.h"
10#include "qlayout.h"
11#if QT_CONFIG(radiobutton)
12#include "qradiobutton.h"
13#endif
14#include "qstyle.h"
15#include "qstyleoption.h"
16#include "qstylepainter.h"
17#if QT_CONFIG(accessibility)
18#include "qaccessible.h"
19#endif
20#include <private/qwidget_p.h>
21#include <private/qguiapplication_p.h>
22#include <qpa/qplatformtheme.h>
23
24#include "qdebug.h"
25#include <QtCore/qpointer.h>
26
28
30{
31 Q_DECLARE_PUBLIC(QGroupBox)
32
33public:
34 void skip();
35 void init();
36 void calculateFrame();
38 int align;
39#ifndef QT_NO_SHORTCUT
41#endif
42
43 void _q_fixFocus(Qt::FocusReason reason);
44 void _q_setChildrenEnabled(bool b);
45 void click();
46 bool flat;
48 bool checked;
49 bool hover;
52};
53
62{
63 if (!option)
64 return;
65
66 Q_D(const QGroupBox);
67 option->initFrom(this);
68 option->text = d->title;
69 option->lineWidth = 1;
70 option->midLineWidth = 0;
71 option->textAlignment = Qt::Alignment(d->align);
72 option->activeSubControls |= d->pressedControl;
73 option->subControls = QStyle::SC_GroupBoxFrame;
74
75 option->state.setFlag(QStyle::State_MouseOver, d->hover);
76 if (d->flat)
78
79 if (d->checkable) {
80 option->subControls |= QStyle::SC_GroupBoxCheckBox;
81 option->state |= (d->checked ? QStyle::State_On : QStyle::State_Off);
82 if ((d->pressedControl == QStyle::SC_GroupBoxCheckBox
83 || d->pressedControl == QStyle::SC_GroupBoxLabel) && (d->hover || d->overCheckBox))
85 }
86
87 if (!option->palette.isBrushSet(isEnabled() ? QPalette::Active :
89 option->textColor = QColor(style()->styleHint(QStyle::SH_GroupBox_TextLabelColor,
90 option, this));
91
92 if (!d->title.isEmpty())
93 option->subControls |= QStyle::SC_GroupBoxLabel;
94}
95
97{
98 Q_Q(QGroupBox);
99
100 QPointer<QGroupBox> guard(q);
101 q->setChecked(!checked);
102 if (!guard)
103 return;
104 emit q->clicked(checked);
105}
106
148 : QWidget(*new QGroupBoxPrivate, parent, { })
149{
150 Q_D(QGroupBox);
151 d->init();
152}
153
159 : QGroupBox(parent)
160{
162}
163
164
171
173{
174 Q_Q(QGroupBox);
176#ifndef QT_NO_SHORTCUT
177 shortcutId = 0;
178#endif
179 flat = false;
180 checkable = false;
181 checked = true;
182 hover = false;
183 overCheckBox = false;
188}
189
191{
192 Q_D(QGroupBox);
193 if (d->title == title) // no change
194 return;
195 d->title = title;
196#ifndef QT_NO_SHORTCUT
197 releaseShortcut(d->shortcutId);
199#endif
200 d->calculateFrame();
201
202 update();
204#if QT_CONFIG(accessibility)
205 QAccessibleEvent event(this, QAccessible::NameChanged);
206 QAccessible::updateAccessibility(&event);
207#endif
208}
209
230{
231 Q_D(const QGroupBox);
232 return d->title;
233}
234
253Qt::Alignment QGroupBox::alignment() const
254{
255 Q_D(const QGroupBox);
256 return QFlag(d->align);
257}
258
260{
261 Q_D(QGroupBox);
262 d->align = alignment;
264 update();
265}
266
273
284
287{
288 Q_D(QGroupBox);
289#ifndef QT_NO_SHORTCUT
290 if (e->type() == QEvent::Shortcut) {
291 QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
292 if (se->shortcutId() == d->shortcutId) {
293 if (!isCheckable()) {
294 d->_q_fixFocus(Qt::ShortcutFocusReason);
295 } else {
296 d->click();
298 }
299 return true;
300 }
301 }
302#endif
305 switch (e->type()) {
307 case QEvent::HoverMove: {
309 static_cast<QHoverEvent *>(e)->position().toPoint(),
310 this);
311 bool oldHover = d->hover;
312 d->hover = d->checkable && (control == QStyle::SC_GroupBoxLabel || control == QStyle::SC_GroupBoxCheckBox);
313 if (oldHover != d->hover) {
316 update(rect);
317 }
318 return true;
319 }
321 d->hover = false;
322 if (d->checkable) {
325 update(rect);
326 }
327 return true;
328 case QEvent::KeyPress: {
329 QKeyEvent *k = static_cast<QKeyEvent*>(e);
330 const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
332 .value<QList<Qt::Key>>();
333 if (!k->isAutoRepeat() && buttonPressKeys.contains(k->key())) {
334 d->pressedControl = QStyle::SC_GroupBoxCheckBox;
336 return true;
337 }
338 break;
339 }
340 case QEvent::KeyRelease: {
341 QKeyEvent *k = static_cast<QKeyEvent*>(e);
342 const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
344 .value<QList<Qt::Key>>();
345 if (!k->isAutoRepeat() && buttonPressKeys.contains(k->key())) {
346 bool toggle = (d->pressedControl == QStyle::SC_GroupBoxLabel
347 || d->pressedControl == QStyle::SC_GroupBoxCheckBox);
348 d->pressedControl = QStyle::SC_None;
349 if (toggle)
350 d->click();
351 return true;
352 }
353 break;
354 }
355 default:
356 break;
357 }
358 return QWidget::event(e);
359}
360
363{
364 Q_D(QGroupBox);
365 /*
366 Children might have been enabled after being added to the group box, in which case
367 the childEvent handler ran too early, and we need to disabled children again.
368 */
369 if (!(c->added() || c->polished()) || !c->child()->isWidgetType())
370 return;
371 QWidget *w = static_cast<QWidget*>(c->child());
372 if (w->isWindow())
373 return;
374 if (d->checkable) {
375 if (d->checked) {
376 if (!w->testAttribute(Qt::WA_ForceDisabled))
377 w->setEnabled(true);
378 } else {
379 if (w->isEnabled()) {
380 w->setEnabled(false);
381 w->setAttribute(Qt::WA_ForceDisabled, false);
382 }
383 }
384 }
385}
386
387
396{
397 Q_Q(QGroupBox);
398 QWidget *fw = q->focusWidget();
399 if (!fw || fw == q) {
400 QWidget * best = nullptr;
401 QWidget * candidate = nullptr;
402 QWidget * w = q;
403 while ((w = w->nextInFocusChain()) != q) {
404 if (q->isAncestorOf(w) && (w->focusPolicy() & Qt::TabFocus) == Qt::TabFocus && w->isVisibleTo(q)) {
405#if QT_CONFIG(radiobutton)
406 if (!best && qobject_cast<QRadioButton*>(w) && ((QRadioButton*)w)->isChecked())
407 // we prefer a checked radio button or a widget that
408 // already has focus, if there is one
409 best = w;
410 else
411#endif
412 if (!candidate)
413 // but we'll accept anything that takes focus
414 candidate = w;
415 }
416 }
417 if (best)
418 fw = best;
419 else if (candidate)
420 fw = candidate;
421 }
422 if (fw)
423 fw->setFocus(reason);
424}
425
426/*
427 Sets the right frame rect depending on the title.
428*/
430{
431 Q_Q(QGroupBox);
433 q->initStyleOption(&box);
434 QRect contentsRect = q->style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxContents, q);
435 q->setContentsMargins(contentsRect.left() - box.rect.left(), contentsRect.top() - box.rect.top(),
436 box.rect.right() - contentsRect.right(), box.rect.bottom() - contentsRect.bottom());
438}
439
443{ // note no call to super
444 Q_D(QGroupBox);
445 if (focusPolicy() == Qt::NoFocus) {
446 d->_q_fixFocus(fe->reason());
447 } else {
449 }
450}
451
452
457{
458 Q_D(const QGroupBox);
461
463
464 int baseWidth = metrics.horizontalAdvance(d->title) + metrics.horizontalAdvance(u' ');
465 int baseHeight = metrics.height();
466 if (d->checkable) {
467 baseWidth += style()->pixelMetric(QStyle::PM_IndicatorWidth, &option, this);
469 baseHeight = qMax(baseHeight, style()->pixelMetric(QStyle::PM_IndicatorHeight, &option, this));
470 }
471
472 QSize size = style()->sizeFromContents(QStyle::CT_GroupBox, &option, QSize(baseWidth, baseHeight), this);
473 return size.expandedTo(QWidget::minimumSizeHint());
474}
475
494{
495 Q_D(const QGroupBox);
496 return d->flat;
497}
498
500{
501 Q_D(QGroupBox);
502 if (d->flat == b)
503 return;
504 d->flat = b;
506 update();
507}
508
509
526void QGroupBox::setCheckable(bool checkable)
527{
528 Q_D(QGroupBox);
529
530 bool wasCheckable = d->checkable;
531 d->checkable = checkable;
532
533 if (checkable) {
534 setChecked(true);
535 if (!wasCheckable) {
537 d->_q_setChildrenEnabled(true);
539 }
540 } else {
541 if (wasCheckable) {
543 d->_q_setChildrenEnabled(true);
545 }
546 d->_q_setChildrenEnabled(true);
547 }
548
549 if (wasCheckable != checkable) {
550 d->calculateFrame();
551 update();
552 }
553}
554
556{
557 Q_D(const QGroupBox);
558 return d->checkable;
559}
560
561
563{
564 Q_D(const QGroupBox);
565 return d->checkable && d->checked;
566}
567
568
607{
608 Q_D(QGroupBox);
609 if (d->checkable && b != d->checked) {
610 update();
611 d->checked = b;
612 d->_q_setChildrenEnabled(b);
613#if QT_CONFIG(accessibility)
615 st.checked = true;
616 QAccessibleStateChangeEvent e(this, st);
617 QAccessible::updateAccessibility(&e);
618#endif
619 emit toggled(b);
620 }
621}
622
623/*
624 sets all children of the group box except the qt_groupbox_checkbox
625 to either disabled/enabled
626*/
628{
629 Q_Q(QGroupBox);
630 for (QObject *o : q->children()) {
631 if (o->isWidgetType()) {
632 QWidget *w = static_cast<QWidget *>(o);
633 if (b) {
634 if (!w->testAttribute(Qt::WA_ForceDisabled))
635 w->setEnabled(true);
636 } else {
637 if (w->isEnabled()) {
638 w->setEnabled(false);
639 w->setAttribute(Qt::WA_ForceDisabled, false);
640 }
641 }
642 }
643 }
644}
645
648{
649 Q_D(QGroupBox);
650 if (ev->type() == QEvent::EnabledChange) {
651 if (d->checkable && isEnabled()) {
652 // we are being enabled - disable children
653 if (!d->checked)
654 d->_q_setChildrenEnabled(false);
655 }
656 } else if (ev->type() == QEvent::FontChange
657#ifdef Q_OS_MAC
658 || ev->type() == QEvent::MacSizeChange
659#endif
660 || ev->type() == QEvent::StyleChange) {
661 d->calculateFrame();
662 }
664}
665
668{
669 if (event->button() != Qt::LeftButton) {
670 event->ignore();
671 return;
672 }
673
674 Q_D(QGroupBox);
677 d->pressedControl = style()->hitTestComplexControl(QStyle::CC_GroupBox, &box,
678 event->position().toPoint(), this);
679 if (d->checkable && (d->pressedControl & (QStyle::SC_GroupBoxCheckBox | QStyle::SC_GroupBoxLabel))) {
680 d->overCheckBox = true;
682 } else {
683 event->ignore();
684 }
685}
686
689{
690 Q_D(QGroupBox);
694 event->position().toPoint(), this);
695 bool oldOverCheckBox = d->overCheckBox;
696 d->overCheckBox = (pressed == QStyle::SC_GroupBoxCheckBox || pressed == QStyle::SC_GroupBoxLabel);
697 if (d->checkable && (d->pressedControl == QStyle::SC_GroupBoxCheckBox || d->pressedControl == QStyle::SC_GroupBoxLabel)
698 && (d->overCheckBox != oldOverCheckBox))
700
701 event->ignore();
702}
703
706{
707 if (event->button() != Qt::LeftButton) {
708 event->ignore();
709 return;
710 }
711
712 Q_D(QGroupBox);
713 if (!d->overCheckBox) {
714 event->ignore();
715 return;
716 }
720 event->position().toPoint(), this);
721 bool toggle = d->checkable && (released == QStyle::SC_GroupBoxLabel
722 || released == QStyle::SC_GroupBoxCheckBox);
723 d->pressedControl = QStyle::SC_None;
724 d->overCheckBox = false;
725 if (toggle)
726 d->click();
727 else if (d->checkable)
729}
730
732
733#include "moc_qgroupbox.cpp"
\inmodule QtGui
\inmodule QtCore
Definition qcoreevent.h:379
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
\inmodule QtCore
Definition qcoreevent.h:45
@ EnabledChange
Definition qcoreevent.h:134
@ StyleChange
Definition qcoreevent.h:136
@ FontChange
Definition qcoreevent.h:133
@ KeyRelease
Definition qcoreevent.h:65
@ KeyPress
Definition qcoreevent.h:64
@ HoverLeave
Definition qcoreevent.h:176
@ HoverEnter
Definition qcoreevent.h:175
@ HoverMove
Definition qcoreevent.h:177
@ MacSizeChange
Definition qcoreevent.h:217
Type type() const
Returns the event type.
Definition qcoreevent.h:304
Definition qflags.h:17
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:470
\reentrant \inmodule QtGui
QStyle::SubControl pressedControl
Definition qgroupbox.cpp:51
void _q_setChildrenEnabled(bool b)
void _q_fixFocus(Qt::FocusReason reason)
The QGroupBox widget provides a group box frame with a title.
Definition qgroupbox.h:17
void paintEvent(QPaintEvent *event) override
\reimp
QString title
the group box title text
Definition qgroupbox.h:20
virtual void initStyleOption(QStyleOptionGroupBox *option) const
Initialize option with the values from this QGroupBox.
Definition qgroupbox.cpp:61
void mouseReleaseEvent(QMouseEvent *event) override
\reimp
QGroupBox(QWidget *parent=nullptr)
Constructs a group box widget with the given parent but with no title.
bool isChecked() const
void mousePressEvent(QMouseEvent *event) override
\reimp
void resizeEvent(QResizeEvent *event) override
\reimp
void toggled(bool)
If the group box is checkable, this signal is emitted when the check box is toggled.
bool event(QEvent *event) override
\reimp
void childEvent(QChildEvent *event) override
\reimp
bool isFlat() const
bool checkable
whether the group box has a checkbox in its title
Definition qgroupbox.h:23
void mouseMoveEvent(QMouseEvent *event) override
\reimp
bool isCheckable() const
void setChecked(bool checked)
void setCheckable(bool checkable)
void changeEvent(QEvent *event) override
\reimp
void setAlignment(int alignment)
Qt::Alignment alignment
the alignment of the group box title.
Definition qgroupbox.h:21
~QGroupBox()
Destroys the group box.
void focusInEvent(QFocusEvent *event) override
\reimp
void setFlat(bool flat)
QSize minimumSizeHint() const override
\reimp
void setTitle(const QString &title)
static QPlatformTheme * platformTheme()
\inmodule QtGui
Definition qevent.h:246
The QKeyEvent class describes a key event.
Definition qevent.h:424
bool isAutoRepeat() const
Returns true if this event comes from an auto-repeating key; returns false if it comes from an initia...
Definition qevent.h:444
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:434
static QKeySequence mnemonic(const QString &text)
Returns the shortcut key sequence for the mnemonic in text, or an empty key sequence if no mnemonics ...
\inmodule QtGui
Definition qevent.h:196
\inmodule QtCore
Definition qobject.h:103
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:486
@ Disabled
Definition qpalette.h:49
@ WindowText
Definition qpalette.h:51
The QRadioButton widget provides a radio button with a text label.
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:182
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:176
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:173
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:179
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:548
The QShortcutEvent class provides an event which is generated when the user presses a key combination...
The QSizePolicy class is a layout attribute describing horizontal and vertical resizing policy.
Definition qsizepolicy.h:18
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\variable QStyleOptionFrame::features
The QStylePainter class is a convenience class for drawing QStyle elements inside a widget.
@ State_MouseOver
Definition qstyle.h:80
@ State_Sunken
Definition qstyle.h:69
@ State_Off
Definition qstyle.h:70
@ State_On
Definition qstyle.h:72
@ CT_GroupBox
Definition qstyle.h:567
virtual QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget=nullptr) const =0
Returns the rectangle containing the specified subControl of the given complex control (with the styl...
virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w=nullptr) const =0
Returns the size of the element described by the specified option and type, based on the provided con...
@ SH_GroupBox_TextLabelColor
Definition qstyle.h:617
virtual SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, const QPoint &pt, const QWidget *widget=nullptr) const =0
Returns the sub control at the given position in the given complex control (with the style options sp...
@ PM_IndicatorWidth
Definition qstyle.h:462
@ PM_CheckBoxLabelSpacing
Definition qstyle.h:502
@ PM_IndicatorHeight
Definition qstyle.h:463
@ CC_GroupBox
Definition qstyle.h:339
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
Returns the value of the given pixel metric.
@ SE_GroupBoxLayoutItem
Definition qstyle.h:301
SubControl
This enum describes the available sub controls.
Definition qstyle.h:347
@ SC_GroupBoxContents
Definition qstyle.h:392
@ SC_GroupBoxCheckBox
Definition qstyle.h:390
@ SC_GroupBoxLabel
Definition qstyle.h:391
@ SC_None
Definition qstyle.h:348
@ SC_GroupBoxFrame
Definition qstyle.h:393
void setLayoutItemMargins(int left, int top, int right, int bottom)
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void releaseShortcut(int id)
Removes the shortcut with the given id from Qt's shortcut system.
void updateGeometry()
Notifies the layout system that this widget has changed and may need to change geometry.
void setEnabled(bool)
Definition qwidget.cpp:3358
QFontMetrics fontMetrics() const
Returns the font metrics for the widget's current font.
Definition qwidget.h:847
QWidget * focusWidget() const
Returns the last child of this widget that setFocus had been called on.
Definition qwidget.cpp:6828
virtual void focusInEvent(QFocusEvent *event)
This event handler can be reimplemented in a subclass to receive keyboard focus events (focus receive...
Definition qwidget.cpp:9665
void setFocusPolicy(Qt::FocusPolicy policy)
Definition qwidget.cpp:7822
QSize minimumSizeHint
the recommended minimum size for the widget
Definition qwidget.h:149
QRect rect
the internal geometry of the widget excluding any window frame
Definition qwidget.h:116
void setFocus()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:423
bool isEnabled() const
Definition qwidget.h:814
void update()
Updates the widget unless updates are disabled or the widget is hidden.
virtual void changeEvent(QEvent *)
This event handler can be reimplemented to handle state changes.
Definition qwidget.cpp:9382
bool event(QEvent *event) override
This is the main event handler; it handles event event.
Definition qwidget.cpp:8866
int grabShortcut(const QKeySequence &key, Qt::ShortcutContext context=Qt::WindowShortcut)
Adds a shortcut to Qt's shortcut system that watches for the given key sequence in the given context.
QStyle * style() const
Definition qwidget.cpp:2600
virtual void resizeEvent(QResizeEvent *event)
This event handler can be reimplemented in a subclass to receive widget resize events which are passe...
Definition qwidget.cpp:9822
Qt::FocusPolicy focusPolicy
the way the widget accepts keyboard focus
Definition qwidget.h:140
QPainter paint
uint alignment
Combined button and popup list for selecting options.
@ AlignLeft
Definition qnamespace.h:144
@ LeftButton
Definition qnamespace.h:58
@ WA_ForceDisabled
Definition qnamespace.h:299
@ NoFocus
Definition qnamespace.h:107
@ TabFocus
Definition qnamespace.h:108
@ StrongFocus
Definition qnamespace.h:110
FocusReason
@ ShortcutFocusReason
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLboolean GLboolean GLboolean b
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLsizei const GLint * box
struct _cl_event * event
const GLubyte * c
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint GLenum option
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define emit
QString title
[35]