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 QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 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.LGPL3 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-3.0.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 (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qgroupbox.h"
41
42#include "qapplication.h"
43#include "qbitmap.h"
44#include "qdrawutil.h"
45#include "qevent.h"
46#include "qlayout.h"
47#if QT_CONFIG(radiobutton)
48#include "qradiobutton.h"
49#endif
50#include "qstyle.h"
51#include "qstyleoption.h"
52#include "qstylepainter.h"
53#ifndef QT_NO_ACCESSIBILITY
54#include "qaccessible.h"
55#endif
56#include <private/qwidget_p.h>
57
58#include "qdebug.h"
59
60QT_BEGIN_NAMESPACE
61
62class QGroupBoxPrivate : public QWidgetPrivate
63{
64 Q_DECLARE_PUBLIC(QGroupBox)
65
66public:
67 void skip();
68 void init();
69 void calculateFrame();
70 QString title;
71 int align;
72#ifndef QT_NO_SHORTCUT
73 int shortcutId;
74#endif
75
76 void _q_fixFocus(Qt::FocusReason reason);
77 void _q_setChildrenEnabled(bool b);
78 void click();
79 bool flat;
80 bool checkable;
81 bool checked;
82 bool hover;
83 bool overCheckBox;
84 QStyle::SubControl pressedControl;
85};
86
87/*!
88 Initialize \a option with the values from this QGroupBox. This method
89 is useful for subclasses when they need a QStyleOptionGroupBox, but don't want
90 to fill in all the information themselves.
91
92 \sa QStyleOption::initFrom()
93*/
94void QGroupBox::initStyleOption(QStyleOptionGroupBox *option) const
95{
96 if (!option)
97 return;
98
99 Q_D(const QGroupBox);
100 option->initFrom(w: this);
101 option->text = d->title;
102 option->lineWidth = 1;
103 option->midLineWidth = 0;
104 option->textAlignment = Qt::Alignment(d->align);
105 option->activeSubControls |= d->pressedControl;
106 option->subControls = QStyle::SC_GroupBoxFrame;
107
108 option->state.setFlag(flag: QStyle::State_MouseOver, on: d->hover);
109 if (d->flat)
110 option->features |= QStyleOptionFrame::Flat;
111
112 if (d->checkable) {
113 option->subControls |= QStyle::SC_GroupBoxCheckBox;
114 option->state |= (d->checked ? QStyle::State_On : QStyle::State_Off);
115 if ((d->pressedControl == QStyle::SC_GroupBoxCheckBox
116 || d->pressedControl == QStyle::SC_GroupBoxLabel) && (d->hover || d->overCheckBox))
117 option->state |= QStyle::State_Sunken;
118 }
119
120 if (!option->palette.isBrushSet(cg: isEnabled() ? QPalette::Active :
121 QPalette::Disabled, cr: QPalette::WindowText))
122 option->textColor = QColor(style()->styleHint(stylehint: QStyle::SH_GroupBox_TextLabelColor,
123 opt: option, widget: this));
124
125 if (!d->title.isEmpty())
126 option->subControls |= QStyle::SC_GroupBoxLabel;
127}
128
129void QGroupBoxPrivate::click()
130{
131 Q_Q(QGroupBox);
132
133 QPointer<QGroupBox> guard(q);
134 q->setChecked(!checked);
135 if (!guard)
136 return;
137 emit q->clicked(checked);
138}
139
140/*!
141 \class QGroupBox
142 \brief The QGroupBox widget provides a group box frame with a title.
143
144 \ingroup organizers
145 \ingroup geomanagement
146 \inmodule QtWidgets
147
148 \image windows-groupbox.png
149
150 A group box provides a frame, a title on top, a keyboard shortcut, and
151 displays various other widgets inside itself. The keyboard shortcut moves
152 keyboard focus to one of the group box's child widgets.
153
154 QGroupBox also lets you set the \l title (normally set in the
155 constructor) and the title's \l alignment. Group boxes can be
156 \l checkable. Child widgets in checkable group boxes are enabled or
157 disabled depending on whether or not the group box is \l checked.
158
159 You can minimize the space consumption of a group box by enabling
160 the \l flat property. In most \l{QStyle}{styles}, enabling this
161 property results in the removal of the left, right and bottom
162 edges of the frame.
163
164 QGroupBox doesn't automatically lay out the child widgets (which
165 are often \l{QCheckBox}es or \l{QRadioButton}s but can be any
166 widgets). The following example shows how we can set up a
167 QGroupBox with a layout:
168
169 \snippet widgets/groupbox/window.cpp 2
170
171 \sa QButtonGroup, {Group Box Example}
172*/
173
174
175
176/*!
177 Constructs a group box widget with the given \a parent but with no title.
178*/
179
180QGroupBox::QGroupBox(QWidget *parent)
181 : QWidget(*new QGroupBoxPrivate, parent, { })
182{
183 Q_D(QGroupBox);
184 d->init();
185}
186
187/*!
188 Constructs a group box with the given \a title and \a parent.
189*/
190
191QGroupBox::QGroupBox(const QString &title, QWidget *parent)
192 : QGroupBox(parent)
193{
194 setTitle(title);
195}
196
197
198/*!
199 Destroys the group box.
200*/
201QGroupBox::~QGroupBox()
202{
203}
204
205void QGroupBoxPrivate::init()
206{
207 Q_Q(QGroupBox);
208 align = Qt::AlignLeft;
209#ifndef QT_NO_SHORTCUT
210 shortcutId = 0;
211#endif
212 flat = false;
213 checkable = false;
214 checked = true;
215 hover = false;
216 overCheckBox = false;
217 pressedControl = QStyle::SC_None;
218 calculateFrame();
219 q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred,
220 QSizePolicy::GroupBox));
221}
222
223void QGroupBox::setTitle(const QString &title)
224{
225 Q_D(QGroupBox);
226 if (d->title == title) // no change
227 return;
228 d->title = title;
229#ifndef QT_NO_SHORTCUT
230 releaseShortcut(id: d->shortcutId);
231 d->shortcutId = grabShortcut(key: QKeySequence::mnemonic(text: title));
232#endif
233 d->calculateFrame();
234
235 update();
236 updateGeometry();
237#ifndef QT_NO_ACCESSIBILITY
238 QAccessibleEvent event(this, QAccessible::NameChanged);
239 QAccessible::updateAccessibility(event: &event);
240#endif
241}
242
243/*!
244 \property QGroupBox::title
245 \brief the group box title text
246
247 The group box title text will have a keyboard shortcut if the title
248 contains an ampersand ('&') followed by a letter.
249
250 \snippet code/src_gui_widgets_qgroupbox.cpp 0
251
252 In the example above, \uicontrol Alt+U moves the keyboard focus to the
253 group box. See the \l {QShortcut#mnemonic}{QShortcut}
254 documentation for details (to display an actual ampersand, use
255 '&&').
256
257 There is no default title text.
258
259 \sa alignment
260*/
261
262QString QGroupBox::title() const
263{
264 Q_D(const QGroupBox);
265 return d->title;
266}
267
268/*!
269 \property QGroupBox::alignment
270 \brief the alignment of the group box title.
271
272 Most styles place the title at the top of the frame. The horizontal
273 alignment of the title can be specified using single values from
274 the following list:
275
276 \list
277 \li Qt::AlignLeft aligns the title text with the left-hand side of the group box.
278 \li Qt::AlignRight aligns the title text with the right-hand side of the group box.
279 \li Qt::AlignHCenter aligns the title text with the horizontal center of the group box.
280 \endlist
281
282 The default alignment is Qt::AlignLeft.
283
284 \sa Qt::Alignment
285*/
286Qt::Alignment QGroupBox::alignment() const
287{
288 Q_D(const QGroupBox);
289 return QFlag(d->align);
290}
291
292void QGroupBox::setAlignment(int alignment)
293{
294 Q_D(QGroupBox);
295 d->align = alignment;
296 updateGeometry();
297 update();
298}
299
300/*! \reimp
301*/
302void QGroupBox::resizeEvent(QResizeEvent *e)
303{
304 QWidget::resizeEvent(event: e);
305}
306
307/*! \reimp
308*/
309
310void QGroupBox::paintEvent(QPaintEvent *)
311{
312 QStylePainter paint(this);
313 QStyleOptionGroupBox option;
314 initStyleOption(option: &option);
315 paint.drawComplexControl(cc: QStyle::CC_GroupBox, opt: option);
316}
317
318/*! \reimp */
319bool QGroupBox::event(QEvent *e)
320{
321 Q_D(QGroupBox);
322#ifndef QT_NO_SHORTCUT
323 if (e->type() == QEvent::Shortcut) {
324 QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
325 if (se->shortcutId() == d->shortcutId) {
326 if (!isCheckable()) {
327 d->_q_fixFocus(reason: Qt::ShortcutFocusReason);
328 } else {
329 d->click();
330 setFocus(Qt::ShortcutFocusReason);
331 }
332 return true;
333 }
334 }
335#endif
336 QStyleOptionGroupBox box;
337 initStyleOption(option: &box);
338 switch (e->type()) {
339 case QEvent::HoverEnter:
340 case QEvent::HoverMove: {
341 QStyle::SubControl control = style()->hitTestComplexControl(cc: QStyle::CC_GroupBox, opt: &box,
342 pt: static_cast<QHoverEvent *>(e)->pos(),
343 widget: this);
344 bool oldHover = d->hover;
345 d->hover = d->checkable && (control == QStyle::SC_GroupBoxLabel || control == QStyle::SC_GroupBoxCheckBox);
346 if (oldHover != d->hover) {
347 QRect rect = style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &box, sc: QStyle::SC_GroupBoxCheckBox, widget: this)
348 | style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &box, sc: QStyle::SC_GroupBoxLabel, widget: this);
349 update(rect);
350 }
351 return true;
352 }
353 case QEvent::HoverLeave:
354 d->hover = false;
355 if (d->checkable) {
356 QRect rect = style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &box, sc: QStyle::SC_GroupBoxCheckBox, widget: this)
357 | style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &box, sc: QStyle::SC_GroupBoxLabel, widget: this);
358 update(rect);
359 }
360 return true;
361 case QEvent::KeyPress: {
362 QKeyEvent *k = static_cast<QKeyEvent*>(e);
363 if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) {
364 d->pressedControl = QStyle::SC_GroupBoxCheckBox;
365 update(style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &box, sc: QStyle::SC_GroupBoxCheckBox, widget: this));
366 return true;
367 }
368 break;
369 }
370 case QEvent::KeyRelease: {
371 QKeyEvent *k = static_cast<QKeyEvent*>(e);
372 if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) {
373 bool toggle = (d->pressedControl == QStyle::SC_GroupBoxLabel
374 || d->pressedControl == QStyle::SC_GroupBoxCheckBox);
375 d->pressedControl = QStyle::SC_None;
376 if (toggle)
377 d->click();
378 return true;
379 }
380 break;
381 }
382 default:
383 break;
384 }
385 return QWidget::event(event: e);
386}
387
388/*!\reimp */
389void QGroupBox::childEvent(QChildEvent *c)
390{
391 Q_D(QGroupBox);
392 /*
393 Children might have been enabled after being added to the group box, in which case
394 the childEvent handler ran too early, and we need to disabled children again.
395 */
396 if (!(c->added() || c->polished()) || !c->child()->isWidgetType())
397 return;
398 QWidget *w = static_cast<QWidget*>(c->child());
399 if (w->isWindow())
400 return;
401 if (d->checkable) {
402 if (d->checked) {
403 if (!w->testAttribute(attribute: Qt::WA_ForceDisabled))
404 w->setEnabled(true);
405 } else {
406 if (w->isEnabled()) {
407 w->setEnabled(false);
408 w->setAttribute(Qt::WA_ForceDisabled, on: false);
409 }
410 }
411 }
412}
413
414
415/*!
416 \internal
417
418 This private slot finds a widget in this group box that can accept
419 focus, and gives the focus to that widget.
420*/
421
422void QGroupBoxPrivate::_q_fixFocus(Qt::FocusReason reason)
423{
424 Q_Q(QGroupBox);
425 QWidget *fw = q->focusWidget();
426 if (!fw || fw == q) {
427 QWidget * best = nullptr;
428 QWidget * candidate = nullptr;
429 QWidget * w = q;
430 while ((w = w->nextInFocusChain()) != q) {
431 if (q->isAncestorOf(child: w) && (w->focusPolicy() & Qt::TabFocus) == Qt::TabFocus && w->isVisibleTo(q)) {
432#if QT_CONFIG(radiobutton)
433 if (!best && qobject_cast<QRadioButton*>(object: w) && ((QRadioButton*)w)->isChecked())
434 // we prefer a checked radio button or a widget that
435 // already has focus, if there is one
436 best = w;
437 else
438#endif
439 if (!candidate)
440 // but we'll accept anything that takes focus
441 candidate = w;
442 }
443 }
444 if (best)
445 fw = best;
446 else if (candidate)
447 fw = candidate;
448 }
449 if (fw)
450 fw->setFocus(reason);
451}
452
453/*
454 Sets the right frame rect depending on the title.
455*/
456void QGroupBoxPrivate::calculateFrame()
457{
458 Q_Q(QGroupBox);
459 QStyleOptionGroupBox box;
460 q->initStyleOption(option: &box);
461 QRect contentsRect = q->style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &box, sc: QStyle::SC_GroupBoxContents, widget: q);
462 q->setContentsMargins(left: contentsRect.left() - box.rect.left(), top: contentsRect.top() - box.rect.top(),
463 right: box.rect.right() - contentsRect.right(), bottom: box.rect.bottom() - contentsRect.bottom());
464 setLayoutItemMargins(element: QStyle::SE_GroupBoxLayoutItem, opt: &box);
465}
466
467/*! \reimp
468 */
469void QGroupBox::focusInEvent(QFocusEvent *fe)
470{ // note no call to super
471 Q_D(QGroupBox);
472 if (focusPolicy() == Qt::NoFocus) {
473 d->_q_fixFocus(reason: fe->reason());
474 } else {
475 QWidget::focusInEvent(event: fe);
476 }
477}
478
479
480/*!
481 \reimp
482*/
483QSize QGroupBox::minimumSizeHint() const
484{
485 Q_D(const QGroupBox);
486 QStyleOptionGroupBox option;
487 initStyleOption(option: &option);
488
489 QFontMetrics metrics(fontMetrics());
490
491 int baseWidth = metrics.horizontalAdvance(d->title) + metrics.horizontalAdvance(QLatin1Char(' '));
492 int baseHeight = metrics.height();
493 if (d->checkable) {
494 baseWidth += style()->pixelMetric(metric: QStyle::PM_IndicatorWidth, option: &option);
495 baseWidth += style()->pixelMetric(metric: QStyle::PM_CheckBoxLabelSpacing, option: &option);
496 baseHeight = qMax(a: baseHeight, b: style()->pixelMetric(metric: QStyle::PM_IndicatorHeight, option: &option));
497 }
498
499 QSize size = style()->sizeFromContents(ct: QStyle::CT_GroupBox, opt: &option, contentsSize: QSize(baseWidth, baseHeight), w: this);
500 return size.expandedTo(otherSize: QWidget::minimumSizeHint());
501}
502
503/*!
504 \property QGroupBox::flat
505 \brief whether the group box is painted flat or has a frame
506
507 A group box usually consists of a surrounding frame with a title
508 at the top. If this property is enabled, only the top part of the frame is
509 drawn in most styles; otherwise, the whole frame is drawn.
510
511 By default, this property is disabled, i.e., group boxes are not flat unless
512 explicitly specified.
513
514 \b{Note:} In some styles, flat and non-flat group boxes have similar
515 representations and may not be as distinguishable as they are in other
516 styles.
517
518 \sa title
519*/
520bool QGroupBox::isFlat() const
521{
522 Q_D(const QGroupBox);
523 return d->flat;
524}
525
526void QGroupBox::setFlat(bool b)
527{
528 Q_D(QGroupBox);
529 if (d->flat == b)
530 return;
531 d->flat = b;
532 updateGeometry();
533 update();
534}
535
536
537/*!
538 \property QGroupBox::checkable
539 \brief whether the group box has a checkbox in its title
540
541 If this property is \c true, the group box displays its title using
542 a checkbox in place of an ordinary label. If the checkbox is checked,
543 the group box's children are enabled; otherwise, they are disabled and
544 inaccessible.
545
546 By default, group boxes are not checkable.
547
548 If this property is enabled for a group box, it will also be initially
549 checked to ensure that its contents are enabled.
550
551 \sa checked
552*/
553void QGroupBox::setCheckable(bool checkable)
554{
555 Q_D(QGroupBox);
556
557 bool wasCheckable = d->checkable;
558 d->checkable = checkable;
559
560 if (checkable) {
561 setChecked(true);
562 if (!wasCheckable) {
563 setFocusPolicy(Qt::StrongFocus);
564 d->_q_setChildrenEnabled(b: true);
565 updateGeometry();
566 }
567 } else {
568 if (wasCheckable) {
569 setFocusPolicy(Qt::NoFocus);
570 d->_q_setChildrenEnabled(b: true);
571 updateGeometry();
572 }
573 d->_q_setChildrenEnabled(b: true);
574 }
575
576 if (wasCheckable != checkable) {
577 d->calculateFrame();
578 update();
579 }
580}
581
582bool QGroupBox::isCheckable() const
583{
584 Q_D(const QGroupBox);
585 return d->checkable;
586}
587
588
589bool QGroupBox::isChecked() const
590{
591 Q_D(const QGroupBox);
592 return d->checkable && d->checked;
593}
594
595
596/*!
597 \fn void QGroupBox::toggled(bool on)
598
599 If the group box is checkable, this signal is emitted when the check box
600 is toggled. \a on is true if the check box is checked; otherwise, it is false.
601
602 \sa checkable
603*/
604
605
606/*!
607 \fn void QGroupBox::clicked(bool checked)
608 \since 4.2
609
610 This signal is emitted when the check box is activated (i.e., pressed down
611 then released while the mouse cursor is inside the button), or when the
612 shortcut key is typed. Notably, this signal is \e not emitted if you call
613 setChecked().
614
615 If the check box is checked, \a checked is true; it is false if the check
616 box is unchecked.
617
618 \sa checkable, toggled(), checked
619*/
620
621/*!
622 \property QGroupBox::checked
623 \brief whether the group box is checked
624
625 If the group box is checkable, it is displayed with a check box.
626 If the check box is checked, the group box's children are enabled;
627 otherwise, the children are disabled and are inaccessible to the user.
628
629 By default, checkable group boxes are also checked.
630
631 \sa checkable
632*/
633void QGroupBox::setChecked(bool b)
634{
635 Q_D(QGroupBox);
636 if (d->checkable && b != d->checked) {
637 update();
638 d->checked = b;
639 d->_q_setChildrenEnabled(b);
640#ifndef QT_NO_ACCESSIBILITY
641 QAccessible::State st;
642 st.checked = true;
643 QAccessibleStateChangeEvent e(this, st);
644 QAccessible::updateAccessibility(event: &e);
645#endif
646 emit toggled(b);
647 }
648}
649
650/*
651 sets all children of the group box except the qt_groupbox_checkbox
652 to either disabled/enabled
653*/
654void QGroupBoxPrivate::_q_setChildrenEnabled(bool b)
655{
656 Q_Q(QGroupBox);
657 for (QObject *o : q->children()) {
658 if (o->isWidgetType()) {
659 QWidget *w = static_cast<QWidget *>(o);
660 if (b) {
661 if (!w->testAttribute(attribute: Qt::WA_ForceDisabled))
662 w->setEnabled(true);
663 } else {
664 if (w->isEnabled()) {
665 w->setEnabled(false);
666 w->setAttribute(Qt::WA_ForceDisabled, on: false);
667 }
668 }
669 }
670 }
671}
672
673/*! \reimp */
674void QGroupBox::changeEvent(QEvent *ev)
675{
676 Q_D(QGroupBox);
677 if (ev->type() == QEvent::EnabledChange) {
678 if (d->checkable && isEnabled()) {
679 // we are being enabled - disable children
680 if (!d->checked)
681 d->_q_setChildrenEnabled(b: false);
682 }
683 } else if (ev->type() == QEvent::FontChange
684#ifdef Q_OS_MAC
685 || ev->type() == QEvent::MacSizeChange
686#endif
687 || ev->type() == QEvent::StyleChange) {
688 d->calculateFrame();
689 }
690 QWidget::changeEvent(ev);
691}
692
693/*! \reimp */
694void QGroupBox::mousePressEvent(QMouseEvent *event)
695{
696 if (event->button() != Qt::LeftButton) {
697 event->ignore();
698 return;
699 }
700
701 Q_D(QGroupBox);
702 QStyleOptionGroupBox box;
703 initStyleOption(option: &box);
704 d->pressedControl = style()->hitTestComplexControl(cc: QStyle::CC_GroupBox, opt: &box,
705 pt: event->pos(), widget: this);
706 if (d->checkable && (d->pressedControl & (QStyle::SC_GroupBoxCheckBox | QStyle::SC_GroupBoxLabel))) {
707 d->overCheckBox = true;
708 update(style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &box, sc: QStyle::SC_GroupBoxCheckBox, widget: this));
709 } else {
710 event->ignore();
711 }
712}
713
714/*! \reimp */
715void QGroupBox::mouseMoveEvent(QMouseEvent *event)
716{
717 Q_D(QGroupBox);
718 QStyleOptionGroupBox box;
719 initStyleOption(option: &box);
720 QStyle::SubControl pressed = style()->hitTestComplexControl(cc: QStyle::CC_GroupBox, opt: &box,
721 pt: event->pos(), widget: this);
722 bool oldOverCheckBox = d->overCheckBox;
723 d->overCheckBox = (pressed == QStyle::SC_GroupBoxCheckBox || pressed == QStyle::SC_GroupBoxLabel);
724 if (d->checkable && (d->pressedControl == QStyle::SC_GroupBoxCheckBox || d->pressedControl == QStyle::SC_GroupBoxLabel)
725 && (d->overCheckBox != oldOverCheckBox))
726 update(style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &box, sc: QStyle::SC_GroupBoxCheckBox, widget: this));
727
728 event->ignore();
729}
730
731/*! \reimp */
732void QGroupBox::mouseReleaseEvent(QMouseEvent *event)
733{
734 if (event->button() != Qt::LeftButton) {
735 event->ignore();
736 return;
737 }
738
739 Q_D(QGroupBox);
740 if (!d->overCheckBox) {
741 event->ignore();
742 return;
743 }
744 QStyleOptionGroupBox box;
745 initStyleOption(option: &box);
746 QStyle::SubControl released = style()->hitTestComplexControl(cc: QStyle::CC_GroupBox, opt: &box,
747 pt: event->pos(), widget: this);
748 bool toggle = d->checkable && (released == QStyle::SC_GroupBoxLabel
749 || released == QStyle::SC_GroupBoxCheckBox);
750 d->pressedControl = QStyle::SC_None;
751 d->overCheckBox = false;
752 if (toggle)
753 d->click();
754 else if (d->checkable)
755 update(style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &box, sc: QStyle::SC_GroupBoxCheckBox, widget: this));
756}
757
758QT_END_NAMESPACE
759
760#include "moc_qgroupbox.cpp"
761

source code of qtbase/src/widgets/widgets/qgroupbox.cpp