~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/widgets/qlabel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

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