source: vendor/trolltech/current/src/widgets/qlabel.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: 30.2 KB
Line 
1/**********************************************************************
2** $Id: qlabel.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QLabel widget class
5**
6** Created : 941215
7**
8** Copyright (C) 1992-2002 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 "qlabel.h"
39#ifndef QT_NO_LABEL
40#include "qpainter.h"
41#include "qdrawutil.h"
42#include "qaccel.h"
43#include "qmovie.h"
44#include "qimage.h"
45#include "qbitmap.h"
46#include "qpicture.h"
47#include "qapplication.h"
48#include "qsimplerichtext.h"
49#include "qstylesheet.h"
50#include "qstyle.h"
51
52class QLabelPrivate
53{
54public:
55 QLabelPrivate()
56 :img(0), pix(0), valid_hints( -1 )
57 {}
58 QImage* img; // for scaled contents
59 QPixmap* pix; // for scaled contents
60 QSize sh;
61 QSize msh;
62 int valid_hints; // stores the frameWidth() for the stored size hint, -1 otherwise
63};
64
65
66/*!
67 \class QLabel qlabel.h
68 \brief The QLabel widget provides a text or image display.
69
70 \ingroup basic
71 \ingroup text
72 \mainclass
73
74 QLabel is used for displaying text or an image. No user
75 interaction functionality is provided. The visual appearance of
76 the label can be configured in various ways, and it can be used
77 for specifying a focus accelerator key for another widget.
78
79 A QLabel can contain any of the following content types:
80 \table
81 \header \i Content \i Setting
82 \row \i Plain text
83 \i Pass a QString to setText().
84 \row \i Rich text
85 \i Pass a QString that contains rich text to setText().
86 \row \i A pixmap
87 \i Pass a QPixmap to setPixmap().
88 \row \i A movie
89 \i Pass a QMovie to setMovie().
90 \row \i A number
91 \i Pass an \e int or a \e double to setNum(), which converts
92 the number to plain text.
93 \row \i Nothing
94 \i The same as an empty plain text. This is the default. Set
95 by clear().
96 \endtable
97
98 When the content is changed using any of these functions, any
99 previous content is cleared.
100
101 The look of a QLabel can be tuned in several ways. All the
102 settings of QFrame are available for specifying a widget frame.
103 The positioning of the content within the QLabel widget area can
104 be tuned with setAlignment() and setIndent(). For example, this
105 code sets up a sunken panel with a two-line text in the bottom
106 right corner (both lines being flush with the right side of the
107 label):
108 \code
109 QLabel *label = new QLabel( this );
110 label->setFrameStyle( QFrame::Panel | QFrame::Sunken );
111 label->setText( "first line\nsecond line" );
112 label->setAlignment( AlignBottom | AlignRight );
113 \endcode
114
115 A QLabel is often used as a label for an interactive widget. For
116 this use QLabel provides a useful mechanism for adding an
117 accelerator key (see QAccel) that will set the keyboard focus to
118 the other widget (called the QLabel's "buddy"). For example:
119 \code
120 QLineEdit* phoneEdit = new QLineEdit( this, "phoneEdit" );
121 QLabel* phoneLabel = new QLabel( phoneEdit, "&Phone:", this, "phoneLabel" );
122 \endcode
123
124 In this example, keyboard focus is transferred to the label's
125 buddy (the QLineEdit) when the user presses Alt+P. You can
126 also use the setBuddy() function to accomplish the same thing.
127
128 <img src=qlabel-m.png> <img src=qlabel-w.png>
129
130 \sa QLineEdit, QTextEdit, QPixmap, QMovie,
131 \link guibooks.html#fowler GUI Design Handbook: Label\endlink
132*/
133
134/*!
135 \fn QPicture * QLabel::picture() const
136
137 Returns the label's picture or 0 if the label doesn't have a
138 picture.
139*/
140
141
142/*!
143 Constructs an empty label.
144
145 The \a parent, \a name and widget flag \a f, arguments are passed
146 to the QFrame constructor.
147
148 \sa setAlignment(), setFrameStyle(), setIndent()
149*/
150
151QLabel::QLabel( QWidget *parent, const char *name, WFlags f )
152 : QFrame( parent, name, f | WMouseNoMask )
153{
154 init();
155}
156
157
158/*!
159 Constructs a label that displays the text, \a text.
160
161 The \a parent, \a name and widget flag \a f, arguments are passed
162 to the QFrame constructor.
163
164 \sa setText(), setAlignment(), setFrameStyle(), setIndent()
165*/
166
167QLabel::QLabel( const QString &text, QWidget *parent, const char *name,
168 WFlags f )
169 : QFrame( parent, name, f | WMouseNoMask )
170{
171 init();
172 setText( text );
173}
174
175
176/*!
177 Constructs a label that displays the text \a text. The label has a
178 buddy widget, \a buddy.
179
180 If the \a text contains an underlined letter (a letter preceded by
181 an ampersand, \&), and the text is in plain text format, when the
182 user presses Alt+ the underlined letter, focus is passed to the
183 buddy widget.
184
185 The \a parent, \a name and widget flag, \a f, arguments are passed
186 to the QFrame constructor.
187
188 \sa setText(), setBuddy(), setAlignment(), setFrameStyle(),
189 setIndent()
190*/
191QLabel::QLabel( QWidget *buddy, const QString &text,
192 QWidget *parent, const char *name, WFlags f )
193 : QFrame( parent, name, f | WMouseNoMask )
194{
195 init();
196#ifndef QT_NO_ACCEL
197 setBuddy( buddy );
198#endif
199 setText( text );
200}
201
202/*!
203 Destroys the label.
204*/
205
206QLabel::~QLabel()
207{
208 clearContents();
209 delete d;
210}
211
212
213void QLabel::init()
214{
215 lpixmap = 0;
216#ifndef QT_NO_MOVIE
217 lmovie = 0;
218#endif
219#ifndef QT_NO_ACCEL
220 lbuddy = 0;
221 accel = 0;
222#endif
223 lpixmap = 0;
224#ifndef QT_NO_PICTURE
225 lpicture = 0;
226#endif
227 align = AlignAuto | AlignVCenter | ExpandTabs;
228 extraMargin = -1;
229 autoresize = FALSE;
230 scaledcontents = FALSE;
231 textformat = Qt::AutoText;
232#ifndef QT_NO_RICHTEXT
233 doc = 0;
234#endif
235
236 setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
237 d = new QLabelPrivate;
238}
239
240
241/*!
242 \property QLabel::text
243 \brief the label's text
244
245 If no text has been set this will return an empty string. Setting
246 the text clears any previous content, unless they are the same.
247
248 The text will be interpreted either as a plain text or as a rich
249 text, depending on the text format setting; see setTextFormat().
250 The default setting is \c AutoText, i.e. QLabel will try to
251 auto-detect the format of the text set.
252
253 If the text is interpreted as a plain text and a buddy has been
254 set, the buddy accelerator key is updated from the new text.
255
256 The label resizes itself if auto-resizing is enabled.
257
258 Note that Qlabel is well-suited to display small rich text
259 documents, i.e. those small documents that get their document
260 specific settings (font, text color, link color) from the label's
261 palette and font properties. For large documents, use QTextEdit
262 in read-only mode instead. QTextEdit will flicker less on resize
263 and can also provide a scrollbar when necessary.
264
265 \sa text, setTextFormat(), setBuddy(), alignment
266*/
267
268void QLabel::setText( const QString &text )
269{
270 if ( ltext == text )
271 return;
272 QSize osh = sizeHint();
273#ifndef QT_NO_RICHTEXT
274 bool hadRichtext = doc != 0;
275#endif
276 clearContents();
277 ltext = text;
278#ifndef QT_NO_RICHTEXT
279 bool useRichText = (textformat == RichText ||
280 ( ( textformat == AutoText ) && QStyleSheet::mightBeRichText(ltext) ) );
281#else
282 bool useRichText = TRUE;
283#endif
284#ifndef QT_NO_ACCEL
285 // ### Setting accelerators for rich text labels will not work.
286 // Eg. <b>&gt;Hello</b> will return ALT+G which is clearly
287 // not intended.
288 if ( !useRichText ) {
289 int p = QAccel::shortcutKey( ltext );
290 if ( p ) {
291 if ( !accel )
292 accel = new QAccel( this, "accel label accel" );
293 accel->connectItem( accel->insertItem( p ),
294 this, SLOT(acceleratorSlot()) );
295 }
296 }
297#endif
298#ifndef QT_NO_RICHTEXT
299 if ( useRichText ) {
300 if ( !hadRichtext )
301 align |= WordBreak;
302 QString t = ltext;
303 if ( align & AlignRight )
304 t.prepend( "<div align=\"right\">");
305 else if ( align & AlignHCenter )
306 t.prepend( "<div align=\"center\">");
307 if ( (align & WordBreak) == 0 )
308 t.prepend( "<nobr>" );
309 doc = new QSimpleRichText( t, font() );
310 }
311#endif
312
313 updateLabel( osh );
314}
315
316
317/*!
318 Clears any label contents. Equivalent to setText( "" ).
319*/
320
321void QLabel::clear()
322{
323 setText( QString::fromLatin1("") );
324}
325
326/*!
327 \property QLabel::pixmap
328 \brief the label's pixmap
329
330 If no pixmap has been set this will return an invalid pixmap.
331
332 Setting the pixmap clears any previous content, and resizes the
333 label if \l QLabel::autoResize() is TRUE. The buddy accelerator,
334 if any, is disabled.
335*/
336void QLabel::setPixmap( const QPixmap &pixmap )
337{
338 QSize osh = sizeHint();
339
340 if ( !lpixmap || lpixmap->serialNumber() != pixmap.serialNumber() ) {
341 clearContents();
342 lpixmap = new QPixmap( pixmap );
343 }
344
345 if ( lpixmap->depth() == 1 && !lpixmap->mask() )
346 lpixmap->setMask( *((QBitmap *)lpixmap) );
347
348 updateLabel( osh );
349}
350
351#ifndef QT_NO_PICTURE
352/*!
353 Sets the label contents to \a picture. Any previous content is
354 cleared.
355
356 The buddy accelerator, if any, is disabled.
357
358 \sa picture(), setBuddy()
359*/
360
361void QLabel::setPicture( const QPicture &picture )
362{
363 QSize osh = sizeHint();
364 clearContents();
365 lpicture = new QPicture( picture );
366
367 updateLabel( osh );
368}
369#endif // QT_NO_PICTURE
370
371/*!
372 Sets the label contents to plain text containing the textual
373 representation of integer \a num. Any previous content is cleared.
374 Does nothing if the integer's string representation is the same as
375 the current contents of the label.
376
377 The buddy accelerator, if any, is disabled.
378
379 The label resizes itself if auto-resizing is enabled.
380
381 \sa setText(), QString::setNum(), setBuddy()
382*/
383
384void QLabel::setNum( int num )
385{
386 QString str;
387 str.setNum( num );
388 setText( str );
389}
390
391/*!
392 \overload
393
394 Sets the label contents to plain text containing the textual
395 representation of double \a num. Any previous content is cleared.
396 Does nothing if the double's string representation is the same as
397 the current contents of the label.
398
399 The buddy accelerator, if any, is disabled.
400
401 The label resizes itself if auto-resizing is enabled.
402
403 \sa setText(), QString::setNum(), setBuddy()
404*/
405
406void QLabel::setNum( double num )
407{
408 QString str;
409 str.setNum( num );
410 setText( str );
411}
412
413/*!
414 \property QLabel::alignment
415 \brief the alignment of the label's contents
416
417 The alignment is a bitwise OR of \c Qt::AlignmentFlags and \c
418 Qt::TextFlags values. The \c ExpandTabs, \c SingleLine and \c
419 ShowPrefix flags apply only if the label contains plain text;
420 otherwise they are ignored. The \c DontClip flag is always
421 ignored. \c WordBreak applies to both rich text and plain text
422 labels. The \c BreakAnywhere flag is not supported in QLabel.
423
424 If the label has a buddy, the \c ShowPrefix flag is forced to
425 TRUE.
426
427 The default alignment is \c{AlignAuto | AlignVCenter | ExpandTabs}
428 if the label doesn't have a buddy and \c{AlignAuto | AlignVCenter
429 | ExpandTabs | ShowPrefix} if the label has a buddy. If the label
430 contains rich text, additionally \c WordBreak is turned on.
431
432 \sa Qt::AlignmentFlags, alignment, setBuddy(), text
433*/
434
435void QLabel::setAlignment( int alignment )
436{
437 if ( alignment == align )
438 return;
439 QSize osh = sizeHint();
440#ifndef QT_NO_ACCEL
441 if ( lbuddy )
442 align = alignment | ShowPrefix;
443 else
444#endif
445 align = alignment;
446
447#ifndef QT_NO_RICHTEXT
448 QString t = ltext;
449 if ( !t.isNull() ) {
450 ltext = QString::null;
451 setText( t );
452 }
453#endif
454
455 updateLabel( osh );
456}
457
458
459/*!
460 \property QLabel::indent
461 \brief the label's text indent in pixels
462
463 If a label displays text, the indent applies to the left edge if
464 alignment() is \c AlignLeft, to the right edge if alignment() is
465 \c AlignRight, to the top edge if alignment() is \c AlignTop, and
466 to to the bottom edge if alignment() is \c AlignBottom.
467
468 If indent is negative, or if no indent has been set, the label
469 computes the effective indent as follows: If frameWidth() is 0,
470 the effective indent becomes 0. If frameWidth() is greater than 0,
471 the effective indent becomes half the width of the "x" character
472 of the widget's current font().
473
474 \sa alignment, frameWidth(), font()
475*/
476
477void QLabel::setIndent( int indent )
478{
479 extraMargin = indent;
480 updateLabel( QSize( -1, -1 ) );
481}
482
483
484/*!
485 \fn bool QLabel::autoResize() const
486
487 \obsolete
488
489 Returns TRUE if auto-resizing is enabled, or FALSE if auto-resizing
490 is disabled.
491
492 Auto-resizing is disabled by default.
493
494 \sa setAutoResize()
495*/
496
497/*! \obsolete
498 Enables auto-resizing if \a enable is TRUE, or disables it if \a
499 enable is FALSE.
500
501 When auto-resizing is enabled the label will resize itself to fit
502 the contents whenever the contents change. The top-left corner is
503 not moved. This is useful for QLabel widgets that are not managed by
504 a QLayout (e.g., top-level widgets).
505
506 Auto-resizing is disabled by default.
507
508 \sa autoResize(), adjustSize(), sizeHint()
509*/
510
511void QLabel::setAutoResize( bool enable )
512{
513 if ( (bool)autoresize != enable ) {
514 autoresize = enable;
515 if ( autoresize )
516 adjustSize(); // calls resize which repaints
517 }
518}
519
520
521
522/*!
523 Returns the size that will be used if the width of the label is \a
524 w. If \a w is -1, the sizeHint() is returned.
525*/
526
527QSize QLabel::sizeForWidth( int w ) const
528{
529 QRect br;
530 QPixmap *pix = pixmap();
531#ifndef QT_NO_PICTURE
532 QPicture *pic = picture();
533#else
534 const int pic = 0;
535#endif
536#ifndef QT_NO_MOVIE
537 QMovie *mov = movie();
538#else
539 const int mov = 0;
540#endif
541 int hextra = 2 * frameWidth();
542 int vextra = hextra;
543 QFontMetrics fm( fontMetrics() );
544 int xw = fm.width( 'x' );
545 if ( !mov && !pix && !pic ) {
546 int m = indent();
547 if ( m < 0 && hextra ) // no indent, but we do have a frame
548 m = xw / 2 - margin();
549 if ( m >= 0 ) {
550 int horizAlign = QApplication::horizontalAlignment( align );
551 if ( (horizAlign & AlignLeft) || (horizAlign & AlignRight ) )
552 hextra += m;
553 if ( (align & AlignTop) || (align & AlignBottom ) )
554 vextra += m;
555 }
556 }
557
558 if ( pix )
559 br = pix->rect();
560#ifndef QT_NO_PICTURE
561 else if ( pic )
562 br = pic->boundingRect();
563#endif
564#ifndef QT_NO_MOVIE
565 else if ( mov )
566 br = mov->framePixmap().rect();
567#endif
568#ifndef QT_NO_RICHTEXT
569 else if ( doc ) {
570 int oldW = doc->width();
571 if ( align & WordBreak ) {
572 if ( w < 0 )
573 doc->adjustSize();
574 else
575 doc->setWidth( w-hextra );
576 }
577 br = QRect( 0, 0, doc->widthUsed(), doc->height() );
578 doc->setWidth( oldW );
579 }
580#endif
581 else {
582 bool tryWidth = (w < 0) && (align & WordBreak);
583 if ( tryWidth )
584 w = xw * 80;
585 else if ( w < 0 )
586 w = 2000;
587 w -= hextra;
588 br = fm.boundingRect( 0, 0, w ,2000, alignment(), text() );
589 if ( tryWidth && br.height() < 4*fm.lineSpacing() && br.width() > w/2 )
590 br = fm.boundingRect( 0, 0, w/2, 2000, alignment(), text() );
591 if ( tryWidth && br.height() < 2*fm.lineSpacing() && br.width() > w/4 )
592 br = fm.boundingRect( 0, 0, w/4, 2000, alignment(), text() );
593 }
594 int wid = br.width() + hextra;
595 int hei = br.height() + vextra;
596
597 return QSize( wid, hei );
598}
599
600
601/*!
602 \reimp
603*/
604
605int QLabel::heightForWidth( int w ) const
606{
607 if (
608#ifndef QT_NO_RICHTEXT
609 doc ||
610#endif
611 (align & WordBreak) )
612 return sizeForWidth( w ).height();
613 return QWidget::heightForWidth( w );
614}
615
616
617
618/*!\reimp
619*/
620QSize QLabel::sizeHint() const
621{
622 if ( d->valid_hints != frameWidth() )
623 (void) QLabel::minimumSizeHint();
624 return d->sh;
625}
626
627/*!
628 \reimp
629*/
630
631QSize QLabel::minimumSizeHint() const
632{
633 if ( d->valid_hints == frameWidth() )
634 return d->msh;
635
636 constPolish();
637 d->valid_hints = frameWidth();
638 d->sh = sizeForWidth( -1 );
639 QSize sz( -1, -1 );
640
641 if (
642#ifndef QT_NO_RICHTEXT
643 !doc &&
644#endif
645 (align & WordBreak) == 0 ) {
646 sz = d->sh;
647 } else {
648 // think about caching these for performance
649 sz.rwidth() = sizeForWidth( 0 ).width();
650 sz.rheight() = sizeForWidth(QWIDGETSIZE_MAX).height();
651 if ( d->sh.height() < sz.height() )
652 sz.rheight() = d->sh.height();
653 }
654 if ( sizePolicy().horData() == QSizePolicy::Ignored )
655 sz.rwidth() = -1;
656 if ( sizePolicy().verData() == QSizePolicy::Ignored )
657 sz.rheight() = -1;
658 d->msh = sz;
659 return sz;
660}
661
662/*!
663 \reimp
664*/
665void QLabel::resizeEvent( QResizeEvent* e )
666{
667 QFrame::resizeEvent( e );
668
669#ifdef QT_NO_RICHTEXT
670 static const bool doc = FALSE;
671#endif
672
673 // optimize for standard labels
674 if ( frameShape() == NoFrame && (align & WordBreak) == 0 && !doc &&
675 ( e->oldSize().width() >= e->size().width() && (align & AlignLeft ) == AlignLeft )
676 && ( e->oldSize().height() >= e->size().height() && (align & AlignTop ) == AlignTop ) ) {
677 setWFlags( WResizeNoErase );
678 return;
679 }
680
681 clearWFlags( WResizeNoErase );
682 QRect cr = contentsRect();
683 if ( !lpixmap || !cr.isValid() ||
684 // masked pixmaps can only reduce flicker when being top/left
685 // aligned and when we do not perform scaled contents
686 ( lpixmap->hasAlpha() && ( scaledcontents || ( ( align & (AlignLeft|AlignTop) ) != (AlignLeft|AlignTop) ) ) ) )
687 return;
688
689 setWFlags( WResizeNoErase );
690
691 if ( !scaledcontents ) {
692 // don't we all love QFrame? Reduce pixmap flicker
693 QRegion reg = QRect( QPoint(0, 0), e->size() );
694 reg = reg.subtract( cr );
695 int x = cr.x();
696 int y = cr.y();
697 int w = lpixmap->width();
698 int h = lpixmap->height();
699 if ( (align & Qt::AlignVCenter) == Qt::AlignVCenter )
700 y += cr.height()/2 - h/2;
701 else if ( (align & Qt::AlignBottom) == Qt::AlignBottom)
702 y += cr.height() - h;
703 if ( (align & Qt::AlignRight) == Qt::AlignRight )
704 x += cr.width() - w;
705 else if ( (align & Qt::AlignHCenter) == Qt::AlignHCenter )
706 x += cr.width()/2 - w/2;
707 if ( x > cr.x() )
708 reg = reg.unite( QRect( cr.x(), cr.y(), x - cr.x(), cr.height() ) );
709 if ( y > cr.y() )
710 reg = reg.unite( QRect( cr.x(), cr.y(), cr.width(), y - cr.y() ) );
711
712 if ( x + w < cr.right() )
713 reg = reg.unite( QRect( x + w, cr.y(), cr.right() - x - w, cr.height() ) );
714 if ( y + h < cr.bottom() )
715 reg = reg.unite( QRect( cr.x(), y + h, cr.width(), cr.bottom() - y - h ) );
716
717 erase( reg );
718 }
719}
720
721
722/*!
723 Draws the label contents using the painter \a p.
724*/
725
726void QLabel::drawContents( QPainter *p )
727{
728 QRect cr = contentsRect();
729
730 QPixmap *pix = pixmap();
731#ifndef QT_NO_PICTURE
732 QPicture *pic = picture();
733#else
734 const int pic = 0;
735#endif
736#ifndef QT_NO_MOVIE
737 QMovie *mov = movie();
738#else
739 const int mov = 0;
740#endif
741
742 if ( !mov && !pix && !pic ) {
743 int m = indent();
744 if ( m < 0 && frameWidth() ) // no indent, but we do have a frame
745 m = fontMetrics().width('x') / 2 - margin();
746 if ( m > 0 ) {
747 int hAlign = QApplication::horizontalAlignment( align );
748 if ( hAlign & AlignLeft )
749 cr.setLeft( cr.left() + m );
750 if ( hAlign & AlignRight )
751 cr.setRight( cr.right() - m );
752 if ( align & AlignTop )
753 cr.setTop( cr.top() + m );
754 if ( align & AlignBottom )
755 cr.setBottom( cr.bottom() - m );
756 }
757 }
758
759#ifndef QT_NO_MOVIE
760 if ( mov ) {
761 // ### should add movie to qDrawItem
762 QRect r = style().itemRect( p, cr, align, isEnabled(), &(mov->framePixmap()),
763 QString::null );
764 // ### could resize movie frame at this point
765 p->drawPixmap(r.x(), r.y(), mov->framePixmap() );
766 }
767 else
768#endif
769#ifndef QT_NO_RICHTEXT
770 if ( doc ) {
771 doc->setWidth(p, cr.width() );
772 int rh = doc->height();
773 int yo = 0;
774 if ( align & AlignVCenter )
775 yo = (cr.height()-rh)/2;
776 else if ( align & AlignBottom )
777 yo = cr.height()-rh;
778 if (! isEnabled() &&
779 style().styleHint(QStyle::SH_EtchDisabledText, this)) {
780 QColorGroup cg = colorGroup();
781 cg.setColor( QColorGroup::Text, cg.light() );
782 doc->draw(p, cr.x()+1, cr.y()+yo+1, cr, cg, 0);
783 }
784
785 // QSimpleRichText always draws with QColorGroup::Text as with
786 // background mode PaletteBase. QLabel typically has
787 // background mode PaletteBackground, so we create a temporary
788 // color group with the text color adjusted.
789 QColorGroup cg = colorGroup();
790 if ( backgroundMode() != PaletteBase && isEnabled() )
791 cg.setColor( QColorGroup::Text, paletteForegroundColor() );
792
793 doc->draw(p, cr.x(), cr.y()+yo, cr, cg, 0);
794 } else
795#endif
796#ifndef QT_NO_PICTURE
797 if ( pic ) {
798 QRect br = pic->boundingRect();
799 int rw = br.width();
800 int rh = br.height();
801 if ( scaledcontents ) {
802 p->save();
803 p->translate( cr.x(), cr.y() );
804#ifndef QT_NO_TRANSFORMATIONS
805 p->scale( (double)cr.width()/rw, (double)cr.height()/rh );
806#endif
807 p->drawPicture( -br.x(), -br.y(), *pic );
808 p->restore();
809 } else {
810 int xo = 0;
811 int yo = 0;
812 if ( align & AlignVCenter )
813 yo = (cr.height()-rh)/2;
814 else if ( align & AlignBottom )
815 yo = cr.height()-rh;
816 if ( align & AlignRight )
817 xo = cr.width()-rw;
818 else if ( align & AlignHCenter )
819 xo = (cr.width()-rw)/2;
820 p->drawPicture( cr.x()+xo-br.x(), cr.y()+yo-br.y(), *pic );
821 }
822 } else
823#endif
824 {
825#ifndef QT_NO_IMAGE_SMOOTHSCALE
826 if ( scaledcontents && pix ) {
827 if ( !d->img )
828 d->img = new QImage( lpixmap->convertToImage() );
829
830 if ( !d->pix )
831 d->pix = new QPixmap;
832 if ( d->pix->size() != cr.size() )
833 d->pix->convertFromImage( d->img->smoothScale( cr.width(), cr.height() ) );
834 pix = d->pix;
835 }
836#endif
837 int alignment = align;
838 if (!style().styleHint(QStyle::SH_UnderlineAccelerator, this))
839 alignment |= NoAccel;
840 // ordinary text or pixmap label
841 style().drawItem( p, cr, alignment, colorGroup(), isEnabled(),
842 pix, ltext );
843 }
844}
845
846
847/*!
848 Updates the label, but not the frame.
849*/
850
851void QLabel::updateLabel( QSize oldSizeHint )
852{
853 d->valid_hints = -1;
854 QSizePolicy policy = sizePolicy();
855 bool wordBreak = align & WordBreak;
856 policy.setHeightForWidth( wordBreak );
857 if ( policy != sizePolicy() )
858 setSizePolicy( policy );
859 if ( sizeHint() != oldSizeHint )
860 updateGeometry();
861 if ( autoresize ) {
862 adjustSize();
863 update( contentsRect() );
864 } else {
865 update( contentsRect() );
866 }
867}
868
869
870/*!
871 \internal
872
873 Internal slot, used to set focus for accelerator labels.
874*/
875#ifndef QT_NO_ACCEL
876void QLabel::acceleratorSlot()
877{
878 if ( !lbuddy )
879 return;
880 QWidget * w = lbuddy;
881 while ( w->focusProxy() )
882 w = w->focusProxy();
883 if ( !w->hasFocus() &&
884 w->isEnabled() &&
885 w->isVisible() &&
886 w->focusPolicy() != NoFocus ) {
887 QFocusEvent::setReason( QFocusEvent::Shortcut );
888 w->setFocus();
889 QFocusEvent::resetReason();
890 }
891}
892#endif
893
894/*!
895 \internal
896
897 Internal slot, used to clean up if the buddy widget dies.
898*/
899#ifndef QT_NO_ACCEL
900void QLabel::buddyDied() // I can't remember if I cried.
901{
902 lbuddy = 0;
903}
904
905/*!
906 Sets this label's buddy to \a buddy.
907
908 When the user presses the accelerator key indicated by this label,
909 the keyboard focus is transferred to the label's buddy widget.
910
911 The buddy mechanism is only available for QLabels that contain
912 plain text in which one letter is prefixed with an ampersand, \&.
913 This letter is set as the accelerator key. The letter is displayed
914 underlined, and the '\&' is not displayed (i.e. the \c ShowPrefix
915 alignment flag is turned on; see setAlignment()).
916
917 In a dialog, you might create two data entry widgets and a label
918 for each, and set up the geometry layout so each label is just to
919 the left of its data entry widget (its "buddy"), for example:
920 \code
921 QLineEdit *nameEd = new QLineEdit( this );
922 QLabel *nameLb = new QLabel( "&Name:", this );
923 nameLb->setBuddy( nameEd );
924 QLineEdit *phoneEd = new QLineEdit( this );
925 QLabel *phoneLb = new QLabel( "&Phone:", this );
926 phoneLb->setBuddy( phoneEd );
927 // ( layout setup not shown )
928 \endcode
929
930 With the code above, the focus jumps to the Name field when the
931 user presses Alt+N, and to the Phone field when the user presses
932 Alt+P.
933
934 To unset a previously set buddy, call this function with \a buddy
935 set to 0.
936
937 \sa buddy(), setText(), QAccel, setAlignment()
938*/
939
940void QLabel::setBuddy( QWidget *buddy )
941{
942 if ( buddy )
943 setAlignment( alignment() | ShowPrefix );
944 else
945 setAlignment( alignment() & ~ShowPrefix );
946
947 if ( lbuddy )
948 disconnect( lbuddy, SIGNAL(destroyed()), this, SLOT(buddyDied()) );
949
950 lbuddy = buddy;
951
952 if ( !lbuddy )
953 return;
954#ifndef QT_NO_RICHTEXT
955 if ( !( textformat == RichText || (textformat == AutoText &&
956 QStyleSheet::mightBeRichText(ltext) ) ) )
957#endif
958 {
959 int p = QAccel::shortcutKey( ltext );
960 if ( p ) {
961 if ( !accel )
962 accel = new QAccel( this, "accel label accel" );
963 accel->connectItem( accel->insertItem( p ),
964 this, SLOT(acceleratorSlot()) );
965 }
966 }
967
968 connect( lbuddy, SIGNAL(destroyed()), this, SLOT(buddyDied()) );
969}
970
971
972/*!
973 Returns this label's buddy, or 0 if no buddy is currently set.
974
975 \sa setBuddy()
976*/
977
978QWidget * QLabel::buddy() const
979{
980 return lbuddy;
981}
982#endif //QT_NO_ACCEL
983
984
985#ifndef QT_NO_MOVIE
986void QLabel::movieUpdated(const QRect& rect)
987{
988 QMovie *mov = movie();
989 if ( mov && !mov->isNull() ) {
990 QRect r = contentsRect();
991 r = style().itemRect( 0, r, align, isEnabled(), &(mov->framePixmap()),
992 QString::null );
993 r.moveBy(rect.x(), rect.y());
994 r.setWidth(QMIN(r.width(), rect.width()));
995 r.setHeight(QMIN(r.height(), rect.height()));
996 repaint( r, mov->framePixmap().mask() != 0 );
997 }
998}
999
1000void QLabel::movieResized( const QSize& size )
1001{
1002 d->valid_hints = -1;
1003 if ( autoresize )
1004 adjustSize();
1005 movieUpdated( QRect( QPoint(0,0), size ) );
1006 updateGeometry();
1007}
1008
1009/*!
1010 Sets the label contents to \a movie. Any previous content is
1011 cleared.
1012
1013 The buddy accelerator, if any, is disabled.
1014
1015 The label resizes itself if auto-resizing is enabled.
1016
1017 \sa movie(), setBuddy()
1018*/
1019
1020void QLabel::setMovie( const QMovie& movie )
1021{
1022 QSize osh = sizeHint();
1023 clearContents();
1024
1025 lmovie = new QMovie( movie );
1026 lmovie->connectResize(this, SLOT(movieResized(const QSize&)));
1027 lmovie->connectUpdate(this, SLOT(movieUpdated(const QRect&)));
1028
1029 if ( !lmovie->running() ) // Assume that if the movie is running,
1030 updateLabel( osh ); // resize/update signals will come soon enough
1031}
1032
1033#endif // QT_NO_MOVIE
1034
1035/*!
1036 \internal
1037
1038 Clears any contents, without updating/repainting the label.
1039*/
1040
1041void QLabel::clearContents()
1042{
1043#ifndef QT_NO_RICHTEXT
1044 delete doc;
1045 doc = 0;
1046#endif
1047
1048 delete lpixmap;
1049 lpixmap = 0;
1050#ifndef QT_NO_PICTURE
1051 delete lpicture;
1052 lpicture = 0;
1053#endif
1054 delete d->img;
1055 d->img = 0;
1056 delete d->pix;
1057 d->pix = 0;
1058
1059 ltext = QString::null;
1060#ifndef QT_NO_ACCEL
1061 if ( accel )
1062 accel->clear();
1063#endif
1064#ifndef QT_NO_MOVIE
1065 if ( lmovie ) {
1066 lmovie->disconnectResize(this, SLOT(movieResized(const QSize&)));
1067 lmovie->disconnectUpdate(this, SLOT(movieUpdated(const QRect&)));
1068 delete lmovie;
1069 lmovie = 0;
1070 }
1071#endif
1072}
1073
1074
1075#ifndef QT_NO_MOVIE
1076
1077/*!
1078 Returns a pointer to the label's movie, or 0 if no movie has been
1079 set.
1080
1081 \sa setMovie()
1082*/
1083
1084QMovie* QLabel::movie() const
1085{
1086 return lmovie;
1087}
1088
1089#endif // QT_NO_MOVIE
1090
1091/*!
1092 \property QLabel::backgroundMode
1093 \brief the label's background mode
1094
1095 Get this property with backgroundMode().
1096
1097 \sa QWidget::setBackgroundMode()
1098*/
1099
1100/*!
1101 \property QLabel::textFormat
1102 \brief the label's text format
1103
1104 See the \c Qt::TextFormat enum for an explanation of the possible
1105 options.
1106
1107 The default format is \c AutoText.
1108
1109 \sa text
1110*/
1111
1112Qt::TextFormat QLabel::textFormat() const
1113{
1114 return textformat;
1115}
1116
1117void QLabel::setTextFormat( Qt::TextFormat format )
1118{
1119 if ( format != textformat ) {
1120 textformat = format;
1121 QString t = ltext;
1122 if ( !t.isNull() ) {
1123 ltext = QString::null;
1124 setText( t );
1125 }
1126 }
1127}
1128
1129/*!
1130 \reimp
1131*/
1132
1133void QLabel::fontChange( const QFont & )
1134{
1135 if ( !ltext.isEmpty() ) {
1136#ifndef QT_NO_RICHTEXT
1137 if ( doc )
1138 doc->setDefaultFont( font() );
1139#endif
1140 updateLabel( QSize( -1, -1 ) );
1141 }
1142}
1143
1144#ifndef QT_NO_IMAGE_SMOOTHSCALE
1145/*!
1146 \property QLabel::scaledContents
1147 \brief whether the label will scale its contents to fill all
1148 available space.
1149
1150 When enabled and the label shows a pixmap, it will scale the
1151 pixmap to fill the available space.
1152
1153 This property's default is FALSE.
1154
1155 \sa setScaledContents()
1156*/
1157bool QLabel::hasScaledContents() const
1158{
1159 return scaledcontents;
1160}
1161
1162void QLabel::setScaledContents( bool enable )
1163{
1164 if ( (bool)scaledcontents == enable )
1165 return;
1166 scaledcontents = enable;
1167 if ( !enable ) {
1168 delete d->img;
1169 d->img = 0;
1170 delete d->pix;
1171 d->pix = 0;
1172 }
1173 update( contentsRect() );
1174}
1175
1176#endif // QT_NO_IMAGE_SMOOTHSCALE
1177
1178/*!
1179 Sets the font used on the QLabel to font \a f.
1180*/
1181
1182void QLabel::setFont( const QFont &f )
1183{
1184 QFrame::setFont( f );
1185}
1186
1187#endif // QT_NO_LABEL
Note: See TracBrowser for help on using the repository browser.