Qt 6.x
The Qt SDK
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
27
29{
30 Q_DECLARE_PUBLIC(QGroupBox)
31
32public:
33 void skip();
34 void init();
35 void calculateFrame();
37 int align;
38#ifndef QT_NO_SHORTCUT
40#endif
41
42 void _q_fixFocus(Qt::FocusReason reason);
43 void _q_setChildrenEnabled(bool b);
44 void click();
45 bool flat;
47 bool checked;
48 bool hover;
51};
52
61{
62 if (!option)
63 return;
64
65 Q_D(const QGroupBox);
66 option->initFrom(this);
67 option->text = d->title;
68 option->lineWidth = 1;
69 option->midLineWidth = 0;
70 option->textAlignment = Qt::Alignment(d->align);
71 option->activeSubControls |= d->pressedControl;
72 option->subControls = QStyle::SC_GroupBoxFrame;
73
74 option->state.setFlag(QStyle::State_MouseOver, d->hover);
75 if (d->flat)
77
78 if (d->checkable) {
79 option->subControls |= QStyle::SC_GroupBoxCheckBox;
80 option->state |= (d->checked ? QStyle::State_On : QStyle::State_Off);
81 if ((d->pressedControl == QStyle::SC_GroupBoxCheckBox
82 || d->pressedControl == QStyle::SC_GroupBoxLabel) && (d->hover || d->overCheckBox))
84 }
85
86 if (!option->palette.isBrushSet(isEnabled() ? QPalette::Active :
88 option->textColor = QColor(style()->styleHint(QStyle::SH_GroupBox_TextLabelColor,
89 option, this));
90
91 if (!d->title.isEmpty())
92 option->subControls |= QStyle::SC_GroupBoxLabel;
93}
94
96{
97 Q_Q(QGroupBox);
98
100 q->setChecked(!checked);
101 if (!guard)
102 return;
103 emit q->clicked(checked);
104}
105
147 : QWidget(*new QGroupBoxPrivate, parent, { })
148{
149 Q_D(QGroupBox);
150 d->init();
151}
152
159{
161}
162
163
168{
169}
170
172{
173 Q_Q(QGroupBox);
175#ifndef QT_NO_SHORTCUT
176 shortcutId = 0;
177#endif
178 flat = false;
179 checkable = false;
180 checked = true;
181 hover = false;
182 overCheckBox = false;
187}
188
190{
191 Q_D(QGroupBox);
192 if (d->title == title) // no change
193 return;
194 d->title = title;
195#ifndef QT_NO_SHORTCUT
196 releaseShortcut(d->shortcutId);
198#endif
199 d->calculateFrame();
200
201 update();
203#if QT_CONFIG(accessibility)
204 QAccessibleEvent event(this, QAccessible::NameChanged);
205 QAccessible::updateAccessibility(&event);
206#endif
207}
208
229{
230 Q_D(const QGroupBox);
231 return d->title;
232}
233
252Qt::Alignment QGroupBox::alignment() const
253{
254 Q_D(const QGroupBox);
255 return QFlag(d->align);
256}
257
259{
260 Q_D(QGroupBox);
261 d->align = alignment;
263 update();
264}
265
269{
271}
272
277{
278 QStylePainter paint(this);
281 paint.drawComplexControl(QStyle::CC_GroupBox, option);
282}
283
286{
287 Q_D(QGroupBox);
288#ifndef QT_NO_SHORTCUT
289 if (e->type() == QEvent::Shortcut) {
290 QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
291 if (se->shortcutId() == d->shortcutId) {
292 if (!isCheckable()) {
293 d->_q_fixFocus(Qt::ShortcutFocusReason);
294 } else {
295 d->click();
297 }
298 return true;
299 }
300 }
301#endif
304 switch (e->type()) {
306 case QEvent::HoverMove: {
308 static_cast<QHoverEvent *>(e)->position().toPoint(),
309 this);
310 bool oldHover = d->hover;
311 d->hover = d->checkable && (control == QStyle::SC_GroupBoxLabel || control == QStyle::SC_GroupBoxCheckBox);
312 if (oldHover != d->hover) {
315 update(rect);
316 }
317 return true;
318 }
320 d->hover = false;
321 if (d->checkable) {
324 update(rect);
325 }
326 return true;
327 case QEvent::KeyPress: {
328 QKeyEvent *k = static_cast<QKeyEvent*>(e);
329 const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
332 if (!k->isAutoRepeat() && buttonPressKeys.contains(k->key())) {
333 d->pressedControl = QStyle::SC_GroupBoxCheckBox;
335 return true;
336 }
337 break;
338 }
339 case QEvent::KeyRelease: {
340 QKeyEvent *k = static_cast<QKeyEvent*>(e);
341 const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
344 if (!k->isAutoRepeat() && buttonPressKeys.contains(k->key())) {
345 bool toggle = (d->pressedControl == QStyle::SC_GroupBoxLabel
346 || d->pressedControl == QStyle::SC_GroupBoxCheckBox);
347 d->pressedControl = QStyle::SC_None;
348 if (toggle)
349 d->click();
350 return true;
351 }
352 break;
353 }
354 default:
355 break;
356 }
357 return QWidget::event(e);
358}
359
362{
363 Q_D(QGroupBox);
364 /*
365 Children might have been enabled after being added to the group box, in which case
366 the childEvent handler ran too early, and we need to disabled children again.
367 */
368 if (!(c->added() || c->polished()) || !c->child()->isWidgetType())
369 return;
370 QWidget *w = static_cast<QWidget*>(c->child());
371 if (w->isWindow())
372 return;
373 if (d->checkable) {
374 if (d->checked) {
375 if (!w->testAttribute(Qt::WA_ForceDisabled))
376 w->setEnabled(true);
377 } else {
378 if (w->isEnabled()) {
379 w->setEnabled(false);
380 w->setAttribute(Qt::WA_ForceDisabled, false);
381 }
382 }
383 }
384}
385
386
395{
396 Q_Q(QGroupBox);
397 QWidget *fw = q->focusWidget();
398 if (!fw || fw == q) {
399 QWidget * best = nullptr;
400 QWidget * candidate = nullptr;
401 QWidget * w = q;
402 while ((w = w->nextInFocusChain()) != q) {
403 if (q->isAncestorOf(w) && (w->focusPolicy() & Qt::TabFocus) == Qt::TabFocus && w->isVisibleTo(q)) {
404#if QT_CONFIG(radiobutton)
405 if (!best && qobject_cast<QRadioButton*>(w) && ((QRadioButton*)w)->isChecked())
406 // we prefer a checked radio button or a widget that
407 // already has focus, if there is one
408 best = w;
409 else
410#endif
411 if (!candidate)
412 // but we'll accept anything that takes focus
413 candidate = w;
414 }
415 }
416 if (best)
417 fw = best;
418 else if (candidate)
419 fw = candidate;
420 }
421 if (fw)
422 fw->setFocus(reason);
423}
424
425/*
426 Sets the right frame rect depending on the title.
427*/
429{
430 Q_Q(QGroupBox);
432 q->initStyleOption(&box);
433 QRect contentsRect = q->style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxContents, q);
434 q->setContentsMargins(contentsRect.left() - box.rect.left(), contentsRect.top() - box.rect.top(),
435 box.rect.right() - contentsRect.right(), box.rect.bottom() - contentsRect.bottom());
437}
438
442{ // note no call to super
443 Q_D(QGroupBox);
444 if (focusPolicy() == Qt::NoFocus) {
445 d->_q_fixFocus(fe->reason());
446 } else {
448 }
449}
450
451
456{
457 Q_D(const QGroupBox);
460
462
463 int baseWidth = metrics.horizontalAdvance(d->title) + metrics.horizontalAdvance(u' ');
464 int baseHeight = metrics.height();
465 if (d->checkable) {
468 baseHeight = qMax(baseHeight, style()->pixelMetric(QStyle::PM_IndicatorHeight, &option));
469 }
470
471 QSize size = style()->sizeFromContents(QStyle::CT_GroupBox, &option, QSize(baseWidth, baseHeight), this);
473}
474
493{
494 Q_D(const QGroupBox);
495 return d->flat;
496}
497
499{
500 Q_D(QGroupBox);
501 if (d->flat == b)
502 return;
503 d->flat = b;
505 update();
506}
507
508
525void QGroupBox::setCheckable(bool checkable)
526{
527 Q_D(QGroupBox);
528
529 bool wasCheckable = d->checkable;
530 d->checkable = checkable;
531
532 if (checkable) {
533 setChecked(true);
534 if (!wasCheckable) {
536 d->_q_setChildrenEnabled(true);
538 }
539 } else {
540 if (wasCheckable) {
542 d->_q_setChildrenEnabled(true);
544 }
545 d->_q_setChildrenEnabled(true);
546 }
547
548 if (wasCheckable != checkable) {
549 d->calculateFrame();
550 update();
551 }
552}
553
555{
556 Q_D(const QGroupBox);
557 return d->checkable;
558}
559
560
562{
563 Q_D(const QGroupBox);
564 return d->checkable && d->checked;
565}
566
567
606{
607 Q_D(QGroupBox);
608 if (d->checkable && b != d->checked) {
609 update();
610 d->checked = b;
611 d->_q_setChildrenEnabled(b);
612#if QT_CONFIG(accessibility)
614 st.checked = true;
615 QAccessibleStateChangeEvent e(this, st);
616 QAccessible::updateAccessibility(&e);
617#endif
618 emit toggled(b);
619 }
620}
621
622/*
623 sets all children of the group box except the qt_groupbox_checkbox
624 to either disabled/enabled
625*/
627{
628 Q_Q(QGroupBox);
629 for (QObject *o : q->children()) {
630 if (o->isWidgetType()) {
631 QWidget *w = static_cast<QWidget *>(o);
632 if (b) {
633 if (!w->testAttribute(Qt::WA_ForceDisabled))
634 w->setEnabled(true);
635 } else {
636 if (w->isEnabled()) {
637 w->setEnabled(false);
638 w->setAttribute(Qt::WA_ForceDisabled, false);
639 }
640 }
641 }
642 }
643}
644
647{
648 Q_D(QGroupBox);
649 if (ev->type() == QEvent::EnabledChange) {
650 if (d->checkable && isEnabled()) {
651 // we are being enabled - disable children
652 if (!d->checked)
653 d->_q_setChildrenEnabled(false);
654 }
655 } else if (ev->type() == QEvent::FontChange
656#ifdef Q_OS_MAC
657 || ev->type() == QEvent::MacSizeChange
658#endif
659 || ev->type() == QEvent::StyleChange) {
660 d->calculateFrame();
661 }
663}
664
667{
668 if (event->button() != Qt::LeftButton) {
669 event->ignore();
670 return;
671 }
672
673 Q_D(QGroupBox);
676 d->pressedControl = style()->hitTestComplexControl(QStyle::CC_GroupBox, &box,
677 event->position().toPoint(), this);
678 if (d->checkable && (d->pressedControl & (QStyle::SC_GroupBoxCheckBox | QStyle::SC_GroupBoxLabel))) {
679 d->overCheckBox = true;
681 } else {
682 event->ignore();
683 }
684}
685
688{
689 Q_D(QGroupBox);
693 event->position().toPoint(), this);
694 bool oldOverCheckBox = d->overCheckBox;
695 d->overCheckBox = (pressed == QStyle::SC_GroupBoxCheckBox || pressed == QStyle::SC_GroupBoxLabel);
696 if (d->checkable && (d->pressedControl == QStyle::SC_GroupBoxCheckBox || d->pressedControl == QStyle::SC_GroupBoxLabel)
697 && (d->overCheckBox != oldOverCheckBox))
699
700 event->ignore();
701}
702
705{
706 if (event->button() != Qt::LeftButton) {
707 event->ignore();
708 return;
709 }
710
711 Q_D(QGroupBox);
712 if (!d->overCheckBox) {
713 event->ignore();
714 return;
715 }
719 event->position().toPoint(), this);
720 bool toggle = d->checkable && (released == QStyle::SC_GroupBoxLabel
721 || released == QStyle::SC_GroupBoxCheckBox);
722 d->pressedControl = QStyle::SC_None;
723 d->overCheckBox = false;
724 if (toggle)
725 d->click();
726 else if (d->checkable)
728}
729
731
732#include "moc_qgroupbox.cpp"
\inmodule QtGui
\inmodule QtCore
Definition qcoreevent.h:372
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:299
Definition qflags.h:17
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:469
Qt::FocusReason reason() const
Returns the reason for this focus event.
Definition qevent.cpp:1566
\reentrant \inmodule QtGui
QStyle::SubControl pressedControl
Definition qgroupbox.cpp:50
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:60
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:245
The QKeyEvent class describes a key event.
Definition qevent.h:423
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:443
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:433
static QKeySequence mnemonic(const QString &text)
Returns the shortcut key sequence for the mnemonic in text, or an empty key sequence if no mnemonics ...
Definition qlist.h:74
\inmodule QtGui
Definition qevent.h:195
\inmodule QtCore
Definition qobject.h:90
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:485
@ Disabled
Definition qpalette.h:48
@ WindowText
Definition qpalette.h:50
virtual QVariant themeHint(ThemeHint hint) const
\inmodule QtCore
Definition qpointer.h:18
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:181
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:178
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:547
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
constexpr QSize expandedTo(const QSize &) const noexcept
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition qsize.h:191
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
\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:565
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:615
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:500
@ 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
T value() const &
Definition qvariant.h:511
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:3365
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:6851
virtual void focusInEvent(QFocusEvent *event)
This event handler can be reimplemented in a subclass to receive keyboard focus events (focus receive...
Definition qwidget.cpp:9711
void setFocusPolicy(Qt::FocusPolicy policy)
Definition qwidget.cpp:7904
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:9428
bool event(QEvent *event) override
This is the main event handler; it handles event event.
Definition qwidget.cpp:8912
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:2607
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:9868
Qt::FocusPolicy focusPolicy
the way the widget accepts keyboard focus
Definition qwidget.h:140
QPainter paint
double e
uint alignment
Combined button and popup list for selecting options.
@ AlignLeft
Definition qnamespace.h:143
@ LeftButton
Definition qnamespace.h:57
@ WA_ForceDisabled
Definition qnamespace.h:298
@ NoFocus
Definition qnamespace.h:106
@ TabFocus
Definition qnamespace.h:107
@ StrongFocus
Definition qnamespace.h:109
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]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent