1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the widgets module of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include "qgroupbox.h"
30
#ifndef QT_NO_GROUPBOX
31
#include "qapplication.h"
33
#include "qcheckbox.h"
34
#include "qdrawutil.h"
38
#include "qradiobutton.h"
40
#include "qstyleoption.h"
41
#ifndef QT_NO_ACCESSIBILITY
42
#include "qaccessible.h"
44
#include <private/qwidget_p.h>
46
class QGroupBoxPrivate : public QWidgetPrivate
48
Q_DECLARE_PUBLIC(QGroupBox)
56
void calculateFrame();
57
void updateCheckBoxGeometry();
63
void setChildrenEnabled(bool b);
71
\class QGroupBox qgroupbox.h
72
\brief The QGroupBox widget provides a group box frame with a title.
75
\ingroup geomanagement
79
A group box provides a frame, a title and a keyboard shortcut, and
80
displays various other widgets inside itself. The title is on top,
81
the keyboard shortcut moves keyboard focus to one of the group
84
QGroupBox also lets you set the \l title (normally set in the
85
constructor) and the title's alignment(). If setCheckable(true) is
86
called then the group box is isCheckable(), and it can be
87
setChecked(). Checkable group boxes child widgets are enabled or
88
disabled depending on whether or not the group box is isChecked().
90
To minimize space consumption, you can remove the right, left and
91
bottom edges of the frame with setFlat().
93
\inlineimage plastique-groupbox.png Screenshot in Plastique style
94
\inlineimage windows-groupbox.png Screenshot in Windows style
102
Constructs a group box widget with no title and parent \a parent.
105
QGroupBox::QGroupBox(QWidget *parent)
106
: QWidget(*new QGroupBoxPrivate, parent, 0)
113
Constructs a group box with the title \a title and parent \a
117
QGroupBox::QGroupBox(const QString &title, QWidget *parent)
118
: QWidget(*new QGroupBoxPrivate, parent, 0)
127
Destroys the group box.
129
QGroupBox::~QGroupBox()
133
void QGroupBoxPrivate::init()
135
align = Qt::AlignLeft;
142
void QGroupBox::setTitle(const QString &title)
145
if (d->title == title) // no change
148
releaseShortcut(d->shortcutId);
150
d->checkbox->setText(d->title);
151
d->shortcutId = 0; // the checkbox does the shortcut for us
153
d->shortcutId = grabShortcut(QKeySequence::mnemonic(title));
156
d->updateCheckBoxGeometry();
160
#ifndef QT_NO_ACCESSIBILITY
161
QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged);
166
\property QGroupBox::title
167
\brief the group box title text.
169
The group box title text will have a focus-change keyboard
170
shortcut if the title contains \&, followed by a letter.
173
g->setTitle("&User information");
175
This produces "\underline{U}ser information"; \key Alt+U moves the keyboard
176
focus to the group box.
178
There is no default title text.
181
QString QGroupBox::title() const
183
Q_D(const QGroupBox);
188
\property QGroupBox::alignment
189
\brief the alignment of the group box title.
191
The title is always placed on the upper frame line. The horizontal
192
alignment can be specified by the alignment parameter.
194
The alignment is one of the following flags:
196
\i \c Qt::AlignLeft aligns the title text to the left.
197
\i \c Qt::AlignRight aligns the title text to the right.
198
\i \c Qt::AlignHCenter aligns the title text centered.
201
The default alignment is \c Qt::AlignLeft.
205
Qt::Alignment QGroupBox::alignment() const
207
Q_D(const QGroupBox);
208
return QFlag(d->align);
211
void QGroupBox::setAlignment(int alignment)
214
d->align = alignment;
215
d->updateCheckBoxGeometry();
221
void QGroupBox::resizeEvent(QResizeEvent *e)
224
QWidget::resizeEvent(e);
225
d->updateCheckBoxGeometry();
231
void QGroupBox::paintEvent(QPaintEvent *event)
234
QPainter paint(this);
236
QRect frameRect = rect();
237
frameRect.setTop(d->topMargin);
238
QStyleOptionFrame opt;
240
opt.rect = frameRect;
242
opt.state |= QStyle::State_Sunken;
244
opt.midLineWidth = 0;
246
if (d->title.size() && !d->checkbox) { // draw title
247
QFontMetrics fm = paint.fontMetrics();
249
int tw = fm.width(d->title + QLatin1Char(' '));
250
int marg = d->bFlat ? 0 : (8 + fm.width(QLatin1Char(' ')));
251
QRect rect = this->rect().adjusted(marg, 0, -marg, 0);
252
QRect r = QStyle::alignedRect(opt.direction, QFlag(d->align | Qt::AlignTop), QSize(tw, h), rect);
253
int va = style()->styleHint(QStyle::SH_GroupBox_TextLabelVerticalAlignment, &opt, this);
254
if(va & Qt::AlignTop)
255
r.translate(0, -fm.descent());
256
int textColor = style()->styleHint(QStyle::SH_GroupBox_TextLabelColor, &opt, this);
257
if (textColor != 0 && !testAttribute(Qt::WA_SetPalette))
258
paint.setPen(QColor::fromRgba((QRgb)textColor));
259
if (!style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
260
va |= Qt::TextHideMnemonic;
261
style()->drawItemText(&paint, r, Qt::TextShowMnemonic | Qt::AlignHCenter | va, palette(),
262
isEnabled(), d->title);
263
paint.setClipRegion(event->region().subtract(r)); // clip everything but title
264
} else if (d->checkbox) {
265
QRect cbClip = d->checkbox->geometry();
266
QFontMetrics fm = paint.fontMetrics();
267
cbClip.setX(cbClip.x() - fm.width(QLatin1Char(' ')));
268
paint.setClipRegion(event->region().subtract(cbClip));
271
QRect fr = frameRect;
272
QPoint p1(fr.x(), fr.y() + 1);
273
QPoint p2(fr.x() + fr.width(), p1.y());
274
// ### This should probably be a style primitive.
275
qDrawShadeLine(&paint, p1, p2, palette(), true, 1, 0);
277
style()->drawPrimitive(QStyle::PE_FrameGroupBox, &opt, &paint, this);
282
bool QGroupBox::event(QEvent *e)
285
if (e->type() == QEvent::Shortcut) {
286
QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
287
if (se->shortcutId() == d->shortcutId) {
292
return QWidget::event(e);
296
void QGroupBox::childEvent(QChildEvent *c)
299
if (c->type() != QEvent::ChildAdded || !c->child()->isWidgetType())
301
QWidget *w = (QWidget*)c->child();
303
if (w == d->checkbox)
305
if (d->checkbox->isChecked()) {
306
if (!w->testAttribute(Qt::WA_ForceDisabled))
309
if (w->isEnabled()) {
310
w->setEnabled(false);
311
w->setAttribute(Qt::WA_ForceDisabled, false);
321
This private slot finds a widget in this group box that can accept
322
focus, and gives the focus to that widget.
325
void QGroupBoxPrivate::fixFocus()
328
QWidget *fw = q->focusWidget();
330
#ifndef QT_NO_RADIOBUTTON
333
QWidget * candidate = 0;
335
while ((w = w->nextInFocusChain()) != q) {
336
if (q->isAncestorOf(w) && (w->focusPolicy() & Qt::TabFocus) == Qt::TabFocus && w->isVisibleTo(q)) {
337
#ifndef QT_NO_RADIOBUTTON
338
if (!best && qobject_cast<QRadioButton*>(w) && ((QRadioButton*)w)->isChecked())
339
// we prefer a checked radio button or a widget that
340
// already has focus, if there is one
345
// but we'll accept anything that takes focus
349
#ifndef QT_NO_RADIOBUTTON
363
Sets the right frame rect depending on the title.
365
void QGroupBoxPrivate::calculateFrame()
368
int va = q->style()->styleHint(QStyle::SH_GroupBox_TextLabelVerticalAlignment, 0, q);
372
QFontMetrics fm = q->fontMetrics();
374
topHeight = checkbox->sizeHint().height();
375
if (va & Qt::AlignTop)
376
topMargin = topHeight;
378
topMargin = topHeight / 2;
379
} else if (title.size()) {
380
topHeight = fm.height();
381
if (va & Qt::AlignVCenter)
382
topMargin = topHeight/2;
383
else if (va & Qt::AlignTop)
384
topMargin = topHeight;
387
int marg = bFlat ? 0 : 2; // ###NEEDS TO BE A STYLE ATTRIBUTE
388
q->setContentsMargins(marg, topHeight + marg, marg, marg);
395
void QGroupBox::focusInEvent(QFocusEvent *)
396
{ // note no call to super
406
QSize QGroupBox::minimumSizeHint() const
408
Q_D(const QGroupBox);
409
QSize sh = QWidget::minimumSizeHint();
411
sh = QSize(d->leftmargin + d->rightmargin + 2, d->topmargin + d->bottommargin + 2);
412
QSize m((d->bFlat ? 0 : 2*8), 0);
415
m.rwidth() += fontMetrics().width(QLatin1Char(' '));
416
sh = sh.expandedTo(d->checkbox->sizeHint() + m);
417
} else if (!d->title.isEmpty()) {
418
sh = sh.expandedTo(fontMetrics().size(0, d->title + QLatin1Char(' ')) + m);
425
\property QGroupBox::flat
426
\brief whether the group box is painted flat or has a frame
428
By default a group box has a surrounding frame, with the title
429
being placed on the upper frame line. In flat mode the right, left
430
and bottom frame lines are omitted, and only the thin line at the
435
bool QGroupBox::isFlat() const
437
Q_D(const QGroupBox);
441
void QGroupBox::setFlat(bool b)
444
if ((bool)d->bFlat == b)
447
d->updateCheckBoxGeometry();
453
\property QGroupBox::checkable
454
\brief Whether the group box has a checkbox in its title.
456
If this property is true, the group box has a checkbox. If the
457
checkbox is checked (which is the default), the group box's
458
children are enabled.
460
setCheckable() controls whether or not the group box has a
461
checkbox, and isCheckable() controls whether the checkbox is
464
void QGroupBox::setCheckable(bool b)
467
if ((d->checkbox != 0) == b)
472
d->checkbox = new QCheckBox(title(), this);
473
d->checkbox->setObjectName(QLatin1String("qt_groupbox_checkbox"));
475
d->setChildrenEnabled(true);
476
connect(d->checkbox, SIGNAL(toggled(bool)),
477
this, SLOT(setChildrenEnabled(bool)));
478
connect(d->checkbox, SIGNAL(toggled(bool)),
479
this, SIGNAL(toggled(bool)));
480
d->updateCheckBoxGeometry();
484
d->setChildrenEnabled(true);
488
QString title = d->title;
490
setTitle(title); // update, including the shortcut
493
bool QGroupBox::isCheckable() const
495
Q_D(const QGroupBox);
496
return (d->checkbox != 0);
500
bool QGroupBox::isChecked() const
502
Q_D(const QGroupBox);
503
return d->checkbox && d->checkbox->isChecked();
508
\fn void QGroupBox::toggled(bool on)
510
If the group box has a check box (see \l isCheckable()) this signal
511
is emitted when the check box is toggled. \a on is true if the check
512
box is checked; otherwise it is false.
516
\property QGroupBox::checked
517
\brief Whether the group box's checkbox is checked.
519
If the group box has a check box (see \l isCheckable()), and the
520
check box is checked, the group box's children
521
are enabled. If the checkbox is unchecked the children are
524
void QGroupBox::setChecked(bool b)
528
d->checkbox->setChecked(b);
532
sets all children of the group box except the qt_groupbox_checkbox
533
to either disabled/enabled
535
void QGroupBoxPrivate::setChildrenEnabled(bool b)
538
QObjectList childs = q->children();
539
if (childs.isEmpty())
541
for (int i = 0; i < childs.size(); ++i) {
542
QObject *o = childs.at(i);
543
if (o->isWidgetType()
546
QWidget *w = static_cast<QWidget *>(o);
548
if (!w->testAttribute(Qt::WA_ForceDisabled))
551
if (w->isEnabled()) {
552
w->setEnabled(false);
553
w->setAttribute(Qt::WA_ForceDisabled, false);
561
void QGroupBox::changeEvent(QEvent *ev)
564
if(ev->type() == QEvent::EnabledChange) {
565
if (d->checkbox && isEnabled()) {
566
// we are being enabled - disable children
567
if (!d->checkbox->isChecked())
568
d->setChildrenEnabled(false);
570
} else if(ev->type() == QEvent::FontChange || ev->type() == QEvent::StyleChange) {
571
d->updateCheckBoxGeometry();
574
QWidget::changeEvent(ev);
578
recalculates and sets the checkbox setGeometry
580
void QGroupBoxPrivate::updateCheckBoxGeometry()
584
QSize cbSize = checkbox->sizeHint();
585
int marg = bFlat ? 0 : (8 + q->fontMetrics().width(QLatin1Char(' ')));
586
QRect rect = q->rect().adjusted(marg, 0, -marg, 0);
587
QRect cbRect = QStyle::alignedRect(q->layoutDirection(), QFlag(this->align | Qt::AlignTop), cbSize, rect);
588
checkbox->setGeometry(cbRect);
594
Use one of the constructors that doesn't take the \a name
595
argument and then use setObjectName() instead.
597
QGroupBox::QGroupBox(QWidget *parent, const char *name)
598
: QWidget(*new QGroupBoxPrivate, parent, 0)
606
Use one of the constructors that doesn't take the \a name
607
argument and then use setObjectName() instead.
609
QGroupBox::QGroupBox(const QString &title, QWidget *parent, const char *name)
610
: QWidget(*new QGroupBoxPrivate, parent, 0)
617
#endif // QT3_SUPPORT
619
#include "moc_qgroupbox.cpp"
621
#endif //QT_NO_GROUPBOX