source: vendor/trolltech/current/src/widgets/qgroupbox.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 24.8 KB
Line 
1/**********************************************************************
2** $Id: qgroupbox.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QGroupBox widget class
5**
6** Created : 950203
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the widgets module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qgroupbox.h"
39#ifndef QT_NO_GROUPBOX
40#include "qlayout.h"
41#include "qpainter.h"
42#include "qbitmap.h"
43#include "qaccel.h"
44#include "qradiobutton.h"
45#include "qfocusdata.h"
46#include "qobjectlist.h"
47#include "qdrawutil.h"
48#include "qapplication.h"
49#include "qstyle.h"
50#include "qcheckbox.h"
51#if defined(QT_ACCESSIBILITY_SUPPORT)
52#include "qaccessible.h"
53#endif
54
55/*!
56 \class QGroupBox qgroupbox.h
57 \brief The QGroupBox widget provides a group box frame with a title.
58
59 \ingroup organizers
60 \ingroup geomanagement
61 \ingroup appearance
62 \mainclass
63
64 A group box provides a frame, a title and a keyboard shortcut, and
65 displays various other widgets inside itself. The title is on top,
66 the keyboard shortcut moves keyboard focus to one of the group
67 box's child widgets, and the child widgets are usually laid out
68 horizontally (or vertically) inside the frame.
69
70 The simplest way to use it is to create a group box with the
71 desired number of columns (or rows) and orientation, and then just
72 create widgets with the group box as parent.
73
74 It is also possible to change the orientation() and number of
75 columns() after construction, or to ignore all the automatic
76 layout support and manage the layout yourself. You can add 'empty'
77 spaces to the group box with addSpace().
78
79 QGroupBox also lets you set the title() (normally set in the
80 constructor) and the title's alignment().
81
82 You can change the spacing used by the group box with
83 setInsideMargin() and setInsideSpacing(). To minimize space
84 consumption, you can remove the right, left and bottom edges of
85 the frame with setFlat().
86
87 <img src=qgrpbox-w.png>
88
89 \sa QButtonGroup
90*/
91
92class QCheckBox;
93
94class QGroupBoxPrivate
95{
96public:
97 QGroupBoxPrivate():
98 spacer( 0 ),
99 checkbox( 0 ) {}
100
101 QSpacerItem *spacer;
102 QCheckBox *checkbox;
103};
104
105
106
107
108/*!
109 Constructs a group box widget with no title.
110
111 The \a parent and \a name arguments are passed to the QWidget
112 constructor.
113
114 This constructor does not do automatic layout.
115*/
116
117QGroupBox::QGroupBox( QWidget *parent, const char *name )
118 : QFrame( parent, name )
119{
120 init();
121}
122
123/*!
124 Constructs a group box with the title \a title.
125
126 The \a parent and \a name arguments are passed to the QWidget
127 constructor.
128
129 This constructor does not do automatic layout.
130*/
131
132QGroupBox::QGroupBox( const QString &title, QWidget *parent, const char *name )
133 : QFrame( parent, name )
134{
135 init();
136 setTitle( title );
137}
138
139/*!
140 Constructs a group box with no title. Child widgets will be
141 arranged in \a strips rows or columns (depending on \a
142 orientation).
143
144 The \a parent and \a name arguments are passed to the QWidget
145 constructor.
146*/
147
148QGroupBox::QGroupBox( int strips, Orientation orientation,
149 QWidget *parent, const char *name )
150 : QFrame( parent, name )
151{
152 init();
153 setColumnLayout( strips, orientation );
154}
155
156/*!
157 Constructs a group box titled \a title. Child widgets will be
158 arranged in \a strips rows or columns (depending on \a
159 orientation).
160
161 The \a parent and \a name arguments are passed to the QWidget
162 constructor.
163*/
164
165QGroupBox::QGroupBox( int strips, Orientation orientation,
166 const QString &title, QWidget *parent,
167 const char *name )
168 : QFrame( parent, name )
169{
170 init();
171 setTitle( title );
172 setColumnLayout( strips, orientation );
173}
174
175/*!
176 Destroys the group box.
177*/
178QGroupBox::~QGroupBox()
179{
180 delete d;
181}
182
183void QGroupBox::init()
184{
185 align = AlignAuto;
186 setFrameStyle( QFrame::GroupBoxPanel | QFrame::Sunken );
187#ifndef QT_NO_ACCEL
188 accel = 0;
189#endif
190 vbox = 0;
191 grid = 0;
192 d = new QGroupBoxPrivate();
193 lenvisible = 0;
194 nCols = nRows = 0;
195 dir = Horizontal;
196 marg = 11;
197 spac = 5;
198 bFlat = FALSE;
199}
200
201void QGroupBox::setTextSpacer()
202{
203 if ( !d->spacer )
204 return;
205 int h = 0;
206 int w = 0;
207 if ( isCheckable() || lenvisible ) {
208 QFontMetrics fm = fontMetrics();
209 int fh = fm.height();
210 if ( isCheckable() ) {
211#ifndef QT_NO_CHECKBOX
212 fh = d->checkbox->sizeHint().height() + 2;
213 w = d->checkbox->sizeHint().width() + 2*fm.width( "xx" );
214#endif
215 } else {
216 fh = fm.height();
217 w = fm.width( str, lenvisible ) + 2*fm.width( "xx" );
218 }
219 h = frameRect().y();
220 if ( layout() ) {
221 int m = layout()->margin();
222 int sp = layout()->spacing();
223 // do we have a child layout?
224 for ( QLayoutIterator it = layout()->iterator(); it.current(); ++it ) {
225 if ( it.current()->layout() ) {
226 m += it.current()->layout()->margin();
227 sp = QMAX( sp, it.current()->layout()->spacing() );
228 break;
229 }
230 }
231 h = QMAX( fh-m, h );
232 h += QMAX( sp - (h+m - fh), 0 );
233 }
234 }
235 d->spacer->changeSize( w, h, QSizePolicy::Minimum, QSizePolicy::Fixed );
236}
237
238
239void QGroupBox::setTitle( const QString &title )
240{
241 if ( str == title ) // no change
242 return;
243 str = title;
244#ifndef QT_NO_ACCEL
245 if ( accel )
246 delete accel;
247 accel = 0;
248 int s = QAccel::shortcutKey( title );
249 if ( s ) {
250 accel = new QAccel( this, "automatic focus-change accelerator" );
251 accel->connectItem( accel->insertItem( s, 0 ),
252 this, SLOT(fixFocus()) );
253 }
254#endif
255#ifndef QT_NO_CHECKBOX
256 if ( d->checkbox ) {
257 d->checkbox->setText( str );
258 updateCheckBoxGeometry();
259 }
260#endif
261 calculateFrame();
262 setTextSpacer();
263
264 update();
265 updateGeometry();
266#if defined(QT_ACCESSIBILITY_SUPPORT)
267 QAccessible::updateAccessibility( this, 0, QAccessible::NameChanged );
268#endif
269}
270
271/*!
272 \property QGroupBox::title
273 \brief the group box title text.
274
275 The group box title text will have a focus-change keyboard
276 accelerator if the title contains \&, followed by a letter.
277
278 \code
279 g->setTitle( "&User information" );
280 \endcode
281 This produces "<u>U</u>ser information"; Alt+U moves the keyboard
282 focus to the group box.
283
284 There is no default title text.
285*/
286
287/*!
288 \property QGroupBox::alignment
289 \brief the alignment of the group box title.
290
291 The title is always placed on the upper frame line. The horizontal
292 alignment can be specified by the alignment parameter.
293
294 The alignment is one of the following flags:
295 \list
296 \i \c AlignAuto aligns the title according to the language,
297 usually to the left.
298 \i \c AlignLeft aligns the title text to the left.
299 \i \c AlignRight aligns the title text to the right.
300 \i \c AlignHCenter aligns the title text centered.
301 \endlist
302
303 The default alignment is \c AlignAuto.
304
305 \sa Qt::AlignmentFlags
306*/
307
308void QGroupBox::setAlignment( int alignment )
309{
310 align = alignment;
311#ifndef QT_NO_CHECKBOX
312 updateCheckBoxGeometry();
313#endif
314 update();
315}
316
317/*! \reimp
318*/
319void QGroupBox::resizeEvent( QResizeEvent *e )
320{
321 QFrame::resizeEvent(e);
322#ifndef QT_NO_CHECKBOX
323 if ( align & AlignRight || align & AlignCenter ||
324 ( QApplication::reverseLayout() && !(align & AlignLeft) ) )
325 updateCheckBoxGeometry();
326#endif
327 calculateFrame();
328}
329
330/*! \reimp
331
332 \internal
333 overrides QFrame::paintEvent
334*/
335
336void QGroupBox::paintEvent( QPaintEvent *event )
337{
338 QPainter paint( this );
339
340 if ( lenvisible && !isCheckable() ) { // draw title
341 QFontMetrics fm = paint.fontMetrics();
342 int h = fm.height();
343 int tw = fm.width( str, lenvisible ) + fm.width(QChar(' '));
344 int x;
345 int marg = bFlat ? 0 : 8;
346 if ( align & AlignHCenter ) // center alignment
347 x = frameRect().width()/2 - tw/2;
348 else if ( align & AlignRight ) // right alignment
349 x = frameRect().width() - tw - marg;
350 else if ( align & AlignLeft ) // left alignment
351 x = marg;
352 else { // auto align
353 if( QApplication::reverseLayout() )
354 x = frameRect().width() - tw - marg;
355 else
356 x = marg;
357 }
358 QRect r( x, 0, tw, h );
359 int va = style().styleHint(QStyle::SH_GroupBox_TextLabelVerticalAlignment, this);
360 if(va & AlignTop)
361 r.moveBy(0, fm.descent());
362 QColor pen( (QRgb) style().styleHint(QStyle::SH_GroupBox_TextLabelColor, this ) );
363 if (!style().styleHint(QStyle::SH_UnderlineAccelerator, this))
364 va |= NoAccel;
365 style().drawItem( &paint, r, ShowPrefix | AlignHCenter | va, colorGroup(),
366 isEnabled(), 0, str, -1, ownPalette() ? 0 : &pen );
367 paint.setClipRegion( event->region().subtract( r ) ); // clip everything but title
368#ifndef QT_NO_CHECKBOX
369 } else if ( d->checkbox ) {
370 QRect cbClip = d->checkbox->geometry();
371 QFontMetrics fm = paint.fontMetrics();
372 cbClip.setX( cbClip.x() - fm.width(QChar(' ')) );
373 cbClip.setWidth( cbClip.width() + fm.width(QChar(' ')) );
374 paint.setClipRegion( event->region().subtract( cbClip ) );
375#endif
376 }
377 if ( bFlat ) {
378 QRect fr = frameRect();
379 QPoint p1( fr.x(), fr.y() + 1 );
380 QPoint p2( fr.x() + fr.width(), p1.y() );
381 // ### This should probably be a style primitive.
382 qDrawShadeLine( &paint, p1, p2, colorGroup(), TRUE,
383 lineWidth(), midLineWidth() );
384 } else {
385 drawFrame(&paint);
386 }
387 drawContents( &paint ); // draw the contents
388}
389
390
391/*!
392 Adds an empty cell at the next free position. If \a size is
393 greater than 0, the empty cell takes \a size to be its fixed width
394 (if orientation() is \c Horizontal) or height (if orientation() is
395 \c Vertical).
396
397 Use this method to separate the widgets in the group box or to
398 skip the next free cell. For performance reasons, call this method
399 after calling setColumnLayout() or by changing the \l
400 QGroupBox::columns or \l QGroupBox::orientation properties. It is
401 generally a good idea to call these methods first (if needed at
402 all), and insert the widgets and spaces afterwards.
403*/
404void QGroupBox::addSpace( int size )
405{
406 QApplication::sendPostedEvents( this, QEvent::ChildInserted );
407
408 if ( nCols <= 0 || nRows <= 0 )
409 return;
410
411 if ( row >= nRows || col >= nCols )
412 grid->expand( row+1, col+1 );
413
414 if ( size > 0 ) {
415 QSpacerItem *spacer
416 = new QSpacerItem( ( dir == Horizontal ) ? 0 : size,
417 ( dir == Vertical ) ? 0 : size,
418 QSizePolicy::Fixed, QSizePolicy::Fixed );
419 grid->addItem( spacer, row, col );
420 }
421
422 skip();
423}
424
425/*!
426 \property QGroupBox::columns
427 \brief the number of columns or rows (depending on \l QGroupBox::orientation) in the group box
428
429 Usually it is not a good idea to set this property because it is
430 slow (it does a complete layout). It is best to set the number
431 of columns directly in the constructor.
432*/
433int QGroupBox::columns() const
434{
435 if ( dir == Horizontal )
436 return nCols;
437 return nRows;
438}
439
440void QGroupBox::setColumns( int c )
441{
442 setColumnLayout( c, dir );
443}
444
445/*!
446 Returns the width of the empty space between the items in the
447 group and the frame of the group.
448
449 Only applies if the group box has a defined orientation.
450
451 The default is usually 11, by may vary depending on the platform
452 and style.
453
454 \sa setInsideMargin(), orientation
455*/
456int QGroupBox::insideMargin() const
457{
458 return marg;
459}
460
461/*!
462 Returns the width of the empty space between each of the items
463 in the group.
464
465 Only applies if the group box has a defined orientation.
466
467 The default is usually 5, by may vary depending on the platform
468 and style.
469
470 \sa setInsideSpacing(), orientation
471*/
472int QGroupBox::insideSpacing() const
473{
474 return spac;
475}
476
477/*!
478 Sets the the width of the inside margin to \a m pixels.
479
480 \sa insideMargin()
481*/
482void QGroupBox::setInsideMargin( int m )
483{
484 marg = m;
485 setColumnLayout( columns(), dir );
486}
487
488/*!
489 Sets the width of the empty space between each of the items in
490 the group to \a s pixels.
491
492 \sa insideSpacing()
493*/
494void QGroupBox::setInsideSpacing( int s )
495{
496 spac = s;
497 setColumnLayout( columns(), dir );
498}
499
500/*!
501 \property QGroupBox::orientation
502 \brief the group box's orientation
503
504 A horizontal group box arranges it's children in columns, while a
505 vertical group box arranges them in rows.
506
507 Usually it is not a good idea to set this property because it is
508 slow (it does a complete layout). It is better to set the
509 orientation directly in the constructor.
510*/
511void QGroupBox::setOrientation( Qt::Orientation o )
512{
513 setColumnLayout( columns(), o );
514}
515
516/*!
517 Changes the layout of the group box. This function is only useful
518 in combination with the default constructor that does not take any
519 layout information. This function will put all existing children
520 in the new layout. It is not good Qt programming style to call
521 this function after children have been inserted. Sets the number
522 of columns or rows to be \a strips, depending on \a direction.
523
524 \sa orientation columns
525*/
526void QGroupBox::setColumnLayout(int strips, Orientation direction)
527{
528 if ( layout() )
529 delete layout();
530
531 vbox = 0;
532 grid = 0;
533
534 if ( strips < 0 ) // if 0, we create the vbox but not the grid. See below.
535 return;
536
537 vbox = new QVBoxLayout( this, marg, 0 );
538
539 d->spacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum,
540 QSizePolicy::Fixed );
541
542 setTextSpacer();
543 vbox->addItem( d->spacer );
544
545 nCols = 0;
546 nRows = 0;
547 dir = direction;
548
549 // Send all child events and ignore them. Otherwise we will end up
550 // with doubled insertion. This won't do anything because nCols ==
551 // nRows == 0.
552 QApplication::sendPostedEvents( this, QEvent::ChildInserted );
553
554 // if 0 or smaller , create a vbox-layout but no grid. This allows
555 // the designer to handle its own grid layout in a group box.
556 if ( strips <= 0 )
557 return;
558
559 dir = direction;
560 if ( dir == Horizontal ) {
561 nCols = strips;
562 nRows = 1;
563 } else {
564 nCols = 1;
565 nRows = strips;
566 }
567 grid = new QGridLayout( nRows, nCols, spac );
568 row = col = 0;
569 grid->setAlignment( AlignTop );
570 vbox->addLayout( grid );
571
572 // Add all children
573 if ( children() ) {
574 QObjectListIt it( *children() );
575 QWidget *w;
576 while( (w=(QWidget *)it.current()) != 0 ) {
577 ++it;
578 if ( w->isWidgetType()
579#ifndef QT_NO_CHECKBOX
580 && w != d->checkbox
581#endif
582 )
583 insertWid( w );
584 }
585 }
586}
587
588
589/*! \reimp */
590bool QGroupBox::event( QEvent * e )
591{
592 if ( e->type() == QEvent::LayoutHint && layout() )
593 setTextSpacer();
594 return QFrame::event( e );
595}
596
597/*!\reimp */
598void QGroupBox::childEvent( QChildEvent *c )
599{
600 if ( !c->inserted() || !c->child()->isWidgetType() )
601 return;
602 QWidget *w = (QWidget*)c->child();
603#ifndef QT_NO_CHECKBOX
604 if ( d->checkbox ) {
605 if ( w == d->checkbox )
606 return;
607 if ( d->checkbox->isChecked() ) {
608 if ( !w->testWState( WState_ForceDisabled ) )
609 w->setEnabled( TRUE );
610 } else {
611 if ( w->isEnabled() ) {
612 w->setEnabled( FALSE );
613 ((QGroupBox*)w)->clearWState( WState_ForceDisabled );
614 }
615 }
616 }
617#endif
618 if ( !grid )
619 return;
620 insertWid( w );
621}
622
623void QGroupBox::insertWid( QWidget* w )
624{
625 if ( row >= nRows || col >= nCols )
626 grid->expand( row+1, col+1 );
627 grid->addWidget( w, row, col );
628 skip();
629 QApplication::postEvent( this, new QEvent( QEvent::LayoutHint ) );
630}
631
632
633void QGroupBox::skip()
634{
635 // Same as QGrid::skip()
636 if ( dir == Horizontal ) {
637 if ( col+1 < nCols ) {
638 col++;
639 } else {
640 col = 0;
641 row++;
642 }
643 } else { //Vertical
644 if ( row+1 < nRows ) {
645 row++;
646 } else {
647 row = 0;
648 col++;
649 }
650 }
651}
652
653
654/*!
655 \internal
656
657 This private slot finds a widget in this group box that can accept
658 focus, and gives the focus to that widget.
659*/
660
661void QGroupBox::fixFocus()
662{
663 QFocusData * fd = focusData();
664 QWidget * orig = fd->home();
665 QWidget * best = 0;
666 QWidget * candidate = 0;
667 QWidget * w = orig;
668 do {
669 QWidget * p = w;
670 while( p && p != this && !p->isTopLevel() )
671 p = p->parentWidget();
672 if ( p == this && ( w->focusPolicy() & TabFocus ) == TabFocus
673 && w->isVisibleTo(this) ) {
674 if ( w->hasFocus()
675#ifndef QT_NO_RADIOBUTTON
676 || ( !best && ::qt_cast<QRadioButton*>(w)
677 && ((QRadioButton*)w)->isChecked() )
678#endif
679 )
680 // we prefer a checked radio button or a widget that
681 // already has focus, if there is one
682 best = w;
683 else if ( !candidate )
684 // but we'll accept anything that takes focus
685 candidate = w;
686 }
687 w = fd->next();
688 } while( w != orig );
689 if ( best )
690 best->setFocus();
691 else if ( candidate )
692 candidate->setFocus();
693}
694
695
696/*
697 Sets the right frame rect depending on the title. Also calculates
698 the visible part of the title.
699*/
700void QGroupBox::calculateFrame()
701{
702 lenvisible = str.length();
703
704 if ( lenvisible && !isCheckable() ) { // do we have a label?
705 QFontMetrics fm = fontMetrics();
706 while ( lenvisible ) {
707 int tw = fm.width( str, lenvisible ) + 4*fm.width(QChar(' '));
708 if ( tw < width() )
709 break;
710 lenvisible--;
711 }
712 if ( lenvisible ) { // but do we also have a visible label?
713 QRect r = rect();
714 int va = style().styleHint(QStyle::SH_GroupBox_TextLabelVerticalAlignment, this);
715 if(va & AlignVCenter)
716 r.setTop( fm.height()/2 ); // frame rect should be
717 else if(va & AlignTop)
718 r.setTop(fm.ascent());
719 setFrameRect( r ); // smaller than client rect
720 return;
721 }
722 } else if ( isCheckable() ) {
723#ifndef QT_NO_CHECKBOX
724 QRect r = rect();
725 int va = style().styleHint(QStyle::SH_GroupBox_TextLabelVerticalAlignment, this);
726 if( va & AlignVCenter )
727 r.setTop( d->checkbox->rect().height()/2 );
728 else if( va & AlignTop )
729 r.setTop( fontMetrics().ascent() );
730 setFrameRect( r );
731 return;
732#endif
733 }
734
735 // no visible label
736 setFrameRect( QRect(0,0,0,0) ); // then use client rect
737}
738
739
740
741/*! \reimp
742 */
743void QGroupBox::focusInEvent( QFocusEvent * )
744{ // note no call to super
745 fixFocus();
746}
747
748
749/*!\reimp
750 */
751void QGroupBox::fontChange( const QFont & oldFont )
752{
753 QWidget::fontChange( oldFont );
754#ifndef QT_NO_CHECKBOX
755 updateCheckBoxGeometry();
756#endif
757 calculateFrame();
758 setTextSpacer();
759}
760
761/*!
762 \reimp
763*/
764
765QSize QGroupBox::sizeHint() const
766{
767 QFontMetrics fm( font() );
768 int tw, th;
769 if ( isCheckable() ) {
770#ifndef QT_NO_CHECKBOX
771 tw = d->checkbox->sizeHint().width() + 2*fm.width( "xx" );
772 th = d->checkbox->sizeHint().height() + fm.width( QChar(' ') );
773#endif
774 } else {
775 tw = fm.width( title() ) + 2 * fm.width( "xx" );
776 th = fm.height() + fm.width( QChar(' ') );
777 }
778
779 QSize s;
780 if ( layout() ) {
781 s = QFrame::sizeHint();
782 return s.expandedTo( QSize( tw, 0 ) );
783 } else {
784 QRect r = childrenRect();
785 QSize s( 100, 50 );
786 s = s.expandedTo( QSize( tw, th ) );
787 if ( r.isNull() )
788 return s;
789
790 return s.expandedTo( QSize( r.width() + 2 * r.x(), r.height()+ 2 * r.y() ) );
791 }
792}
793
794/*!
795 \property QGroupBox::flat
796 \brief whether the group box is painted flat or has a frame
797
798 By default a group box has a surrounding frame, with the title
799 being placed on the upper frame line. In flat mode the right, left
800 and bottom frame lines are omitted, and only the thin line at the
801 top is drawn.
802
803 \sa title
804*/
805bool QGroupBox::isFlat() const
806{
807 return bFlat;
808}
809
810void QGroupBox::setFlat( bool b )
811{
812 if ( (bool)bFlat == b )
813 return;
814 bFlat = b;
815 update();
816}
817
818
819/*!
820 \property QGroupBox::checkable
821 \brief Whether the group box has a checkbox in its title.
822
823 If this property is TRUE, the group box has a checkbox. If the
824 checkbox is checked (which is the default), the group box's
825 children are enabled.
826
827 setCheckable() controls whether or not the group box has a
828 checkbox, and isCheckable() controls whether the checkbox is
829 checked or not.
830*/
831#ifndef QT_NO_CHECKBOX
832void QGroupBox::setCheckable( bool b )
833{
834 if ( (d->checkbox != 0) == b )
835 return;
836
837 if ( b ) {
838 if ( !d->checkbox ) {
839 d->checkbox = new QCheckBox( title(), this, "qt_groupbox_checkbox" );
840 setChecked( TRUE );
841 setChildrenEnabled( TRUE );
842 connect( d->checkbox, SIGNAL( toggled(bool) ),
843 this, SLOT( setChildrenEnabled(bool) ) );
844 connect( d->checkbox, SIGNAL( toggled(bool) ),
845 this, SIGNAL( toggled(bool) ) );
846 updateCheckBoxGeometry();
847 }
848 d->checkbox->show();
849 } else {
850 setChildrenEnabled( TRUE );
851 delete d->checkbox;
852 d->checkbox = 0;
853 }
854 calculateFrame();
855 setTextSpacer();
856 update();
857}
858#endif //QT_NO_CHECKBOX
859
860bool QGroupBox::isCheckable() const
861{
862#ifndef QT_NO_CHECKBOX
863 return ( d->checkbox != 0 );
864#else
865 return FALSE;
866#endif
867}
868
869
870bool QGroupBox::isChecked() const
871{
872#ifndef QT_NO_CHECKBOX
873 return d->checkbox && d->checkbox->isChecked();
874#else
875 return FALSE;
876#endif
877}
878
879
880/*!
881 \fn void QGroupBox::toggled( bool on )
882
883 If the group box has a check box (see \l isCheckable()) this signal
884 is emitted when the check box is toggled. \a on is TRUE if the check
885 box is checked; otherwise it is FALSE.
886*/
887
888/*!
889 \property QGroupBox::checked
890 \brief Whether the group box's checkbox is checked.
891
892 If the group box has a check box (see \l isCheckable()), and the
893 check box is checked (see \l isChecked()), the group box's children
894 are enabled. If the checkbox is unchecked the children are
895 disabled.
896*/
897#ifndef QT_NO_CHECKBOX
898void QGroupBox::setChecked( bool b )
899{
900 if ( d->checkbox )
901 d->checkbox->setChecked( b );
902}
903#endif
904
905/*
906 sets all children of the group box except the qt_groupbox_checkbox
907 to either disabled/enabled
908*/
909void QGroupBox::setChildrenEnabled( bool b )
910{
911 if ( !children() )
912 return;
913 QObjectListIt it( *children() );
914 QObject *o;
915 while( (o = it.current()) ) {
916 ++it;
917 if ( o->isWidgetType()
918#ifndef QT_NO_CHECKBOX
919 && o != d->checkbox
920#endif
921 ) {
922 QWidget *w = (QWidget*)o;
923 if ( b ) {
924 if ( !w->testWState( WState_ForceDisabled ) )
925 w->setEnabled( TRUE );
926 } else {
927 if ( w->isEnabled() ) {
928 w->setEnabled( FALSE );
929 ((QGroupBox*)w)->clearWState( WState_ForceDisabled );
930 }
931 }
932 }
933 }
934}
935
936/*! \reimp */
937void QGroupBox::setEnabled(bool on)
938{
939 QFrame::setEnabled(on);
940 if ( !d->checkbox || !on )
941 return;
942
943#ifndef QT_NO_CHECKBOX
944 // we are being enabled - disable children
945 if ( !d->checkbox->isChecked() )
946 setChildrenEnabled( FALSE );
947#endif
948}
949
950/*
951 recalculates and sets the checkbox setGeometry
952*/
953#ifndef QT_NO_CHECKBOX
954void QGroupBox::updateCheckBoxGeometry()
955{
956 if ( d->checkbox ) {
957 QSize cbSize = d->checkbox->sizeHint();
958 QRect cbRect( 0, 0, cbSize.width(), cbSize.height() );
959
960 int marg = bFlat ? 2 : 8;
961 marg += fontMetrics().width( QChar(' ') );
962
963 if ( align & AlignHCenter ) {
964 cbRect.moveCenter( frameRect().center() );
965 cbRect.moveTop( 0 );
966 } else if ( align & AlignRight ) {
967 cbRect.moveRight( frameRect().right() - marg );
968 } else if ( align & AlignLeft ) {
969 cbRect.moveLeft( frameRect().left() + marg );
970 } else { // auto align
971 if( QApplication::reverseLayout() )
972 cbRect.moveRight( frameRect().right() - marg );
973 else
974 cbRect.moveLeft( frameRect().left() + marg );
975 }
976
977 d->checkbox->setGeometry( cbRect );
978 }
979}
980#endif //QT_NO_CHECKBOX
981
982
983#endif //QT_NO_GROUPBOX
Note: See TracBrowser for help on using the repository browser.