src/gui/widgets/qlabel.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qpainter.h"
       
    43 #include "qevent.h"
       
    44 #include "qdrawutil.h"
       
    45 #include "qapplication.h"
       
    46 #include "qabstractbutton.h"
       
    47 #include "qstyle.h"
       
    48 #include "qstyleoption.h"
       
    49 #include <limits.h>
       
    50 #include "qaction.h"
       
    51 #include "qclipboard.h"
       
    52 #include <qdebug.h>
       
    53 #include <qurl.h>
       
    54 #include "qlabel_p.h"
       
    55 #include "private/qstylesheetstyle_p.h"
       
    56 
       
    57 QT_BEGIN_NAMESPACE
       
    58 
       
    59 /*!
       
    60     \class QLabel
       
    61     \brief The QLabel widget provides a text or image display.
       
    62 
       
    63     \ingroup basicwidgets
       
    64 
       
    65     QLabel is used for displaying text or an image. No user
       
    66     interaction functionality is provided. The visual appearance of
       
    67     the label can be configured in various ways, and it can be used
       
    68     for specifying a focus mnemonic key for another widget.
       
    69 
       
    70     A QLabel can contain any of the following content types:
       
    71 
       
    72     \table
       
    73     \header \o Content \o Setting
       
    74     \row \o Plain text
       
    75          \o Pass a QString to setText().
       
    76     \row \o Rich text
       
    77          \o Pass a QString that contains rich text to setText().
       
    78     \row \o A pixmap
       
    79          \o Pass a QPixmap to setPixmap().
       
    80     \row \o A movie
       
    81          \o Pass a QMovie to setMovie().
       
    82     \row \o A number
       
    83          \o Pass an \e int or a \e double to setNum(), which converts
       
    84             the number to plain text.
       
    85     \row \o Nothing
       
    86          \o The same as an empty plain text. This is the default. Set
       
    87             by clear().
       
    88     \endtable
       
    89 
       
    90     When the content is changed using any of these functions, any
       
    91     previous content is cleared.
       
    92 
       
    93     By default, labels display \l{alignment}{left-aligned, vertically-centered}
       
    94     text and images, where any tabs in the text to be displayed are
       
    95     \l{Qt::TextExpandTabs}{automatically expanded}. However, the look
       
    96     of a QLabel can be adjusted and fine-tuned in several ways.
       
    97 
       
    98     The positioning of the content within the QLabel widget area can
       
    99     be tuned with setAlignment() and setIndent(). Text content can
       
   100     also wrap lines along word boundaries with setWordWrap(). For
       
   101     example, this code sets up a sunken panel with a two-line text in
       
   102     the bottom right corner (both lines being flush with the right
       
   103     side of the label):
       
   104 
       
   105     \snippet doc/src/snippets/code/src_gui_widgets_qlabel.cpp 0
       
   106 
       
   107     The properties and functions QLabel inherits from QFrame can also
       
   108     be used to specify the widget frame to be used for any given label.
       
   109 
       
   110     A QLabel is often used as a label for an interactive widget. For
       
   111     this use QLabel provides a useful mechanism for adding an
       
   112     mnemonic (see QKeySequence) that will set the keyboard focus to
       
   113     the other widget (called the QLabel's "buddy"). For example:
       
   114 
       
   115     \snippet doc/src/snippets/code/src_gui_widgets_qlabel.cpp 1
       
   116 
       
   117     In this example, keyboard focus is transferred to the label's
       
   118     buddy (the QLineEdit) when the user presses Alt+P. If the buddy
       
   119     was a button (inheriting from QAbstractButton), triggering the
       
   120     mnemonic would emulate a button click.
       
   121 
       
   122     \table 100%
       
   123     \row
       
   124     \o \inlineimage macintosh-label.png Screenshot of a Macintosh style label
       
   125     \o A label shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
       
   126     \row
       
   127     \o \inlineimage plastique-label.png Screenshot of a Plastique style label
       
   128     \o A label shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
       
   129     \row
       
   130     \o \inlineimage windowsxp-label.png Screenshot of a Windows XP style label
       
   131     \o A label shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
       
   132     \endtable
       
   133 
       
   134     \sa QLineEdit, QTextEdit, QPixmap, QMovie,
       
   135         {fowler}{GUI Design Handbook: Label}
       
   136 */
       
   137 
       
   138 #ifndef QT_NO_PICTURE
       
   139 /*!
       
   140     Returns the label's picture or 0 if the label doesn't have a
       
   141     picture.
       
   142 */
       
   143 
       
   144 const QPicture *QLabel::picture() const
       
   145 {
       
   146     Q_D(const QLabel);
       
   147     return d->picture;
       
   148 }
       
   149 #endif
       
   150 
       
   151 
       
   152 /*!
       
   153     Constructs an empty label.
       
   154 
       
   155     The \a parent and widget flag \a f, arguments are passed
       
   156     to the QFrame constructor.
       
   157 
       
   158     \sa setAlignment(), setFrameStyle(), setIndent()
       
   159 */
       
   160 QLabel::QLabel(QWidget *parent, Qt::WindowFlags f)
       
   161     : QFrame(*new QLabelPrivate(), parent, f)
       
   162 {
       
   163     Q_D(QLabel);
       
   164     d->init();
       
   165 }
       
   166 
       
   167 /*!
       
   168     Constructs a label that displays the text, \a text.
       
   169 
       
   170     The \a parent and widget flag \a f, arguments are passed
       
   171     to the QFrame constructor.
       
   172 
       
   173     \sa setText(), setAlignment(), setFrameStyle(), setIndent()
       
   174 */
       
   175 QLabel::QLabel(const QString &text, QWidget *parent, Qt::WindowFlags f)
       
   176         : QFrame(*new QLabelPrivate(), parent, f)
       
   177 {
       
   178     Q_D(QLabel);
       
   179     d->init();
       
   180     setText(text);
       
   181 }
       
   182 
       
   183 
       
   184 #ifdef QT3_SUPPORT
       
   185 /*! \obsolete
       
   186     Constructs an empty label.
       
   187 
       
   188     The \a parent, \a name and widget flag \a f, arguments are passed
       
   189     to the QFrame constructor.
       
   190 
       
   191     \sa setAlignment(), setFrameStyle(), setIndent()
       
   192 */
       
   193 
       
   194 QLabel::QLabel(QWidget *parent, const char *name, Qt::WindowFlags f)
       
   195     : QFrame(*new QLabelPrivate(), parent, f)
       
   196 {
       
   197     Q_D(QLabel);
       
   198     if (name)
       
   199         setObjectName(QString::fromAscii(name));
       
   200     d->init();
       
   201 }
       
   202 
       
   203 
       
   204 /*! \obsolete
       
   205     Constructs a label that displays the text, \a text.
       
   206 
       
   207     The \a parent, \a name and widget flag \a f, arguments are passed
       
   208     to the QFrame constructor.
       
   209 
       
   210     \sa setText(), setAlignment(), setFrameStyle(), setIndent()
       
   211 */
       
   212 
       
   213 QLabel::QLabel(const QString &text, QWidget *parent, const char *name,
       
   214                 Qt::WindowFlags f)
       
   215         : QFrame(*new QLabelPrivate(), parent, f)
       
   216 {
       
   217     Q_D(QLabel);
       
   218     if (name)
       
   219         setObjectName(QString::fromAscii(name));
       
   220     d->init();
       
   221     setText(text);
       
   222 }
       
   223 
       
   224 
       
   225 /*! \obsolete
       
   226     Constructs a label that displays the text \a text. The label has a
       
   227     buddy widget, \a buddy.
       
   228 
       
   229     If the \a text contains an underlined letter (a letter preceded by
       
   230     an ampersand, \&), when the user presses Alt+ the underlined letter,
       
   231     focus is passed to the buddy widget.
       
   232 
       
   233     The \a parent, \a name and widget flag, \a f, arguments are passed
       
   234     to the QFrame constructor.
       
   235 
       
   236     \sa setText(), setBuddy(), setAlignment(), setFrameStyle(),
       
   237     setIndent()
       
   238 */
       
   239 QLabel::QLabel(QWidget *buddy, const QString &text,
       
   240                 QWidget *parent, const char *name, Qt::WindowFlags f)
       
   241     : QFrame(*new QLabelPrivate(), parent, f)
       
   242 {
       
   243     Q_D(QLabel);
       
   244     if (name)
       
   245         setObjectName(QString::fromAscii(name));
       
   246     d->init();
       
   247 #ifndef QT_NO_SHORTCUT
       
   248     setBuddy(buddy);
       
   249 #endif
       
   250     setText(text);
       
   251 }
       
   252 #endif //QT3_SUPPORT
       
   253 
       
   254 /*!
       
   255     Destroys the label.
       
   256 */
       
   257 
       
   258 QLabel::~QLabel()
       
   259 {
       
   260     Q_D(QLabel);
       
   261     d->clearContents();
       
   262 }
       
   263 
       
   264 void QLabelPrivate::init()
       
   265 {
       
   266     Q_Q(QLabel);
       
   267 
       
   268     valid_hints = false;
       
   269     margin = 0;
       
   270 #ifndef QT_NO_MOVIE
       
   271     movie = 0;
       
   272 #endif
       
   273 #ifndef QT_NO_SHORTCUT
       
   274     shortcutId = 0;
       
   275 #endif
       
   276     pixmap = 0;
       
   277     scaledpixmap = 0;
       
   278     cachedimage = 0;
       
   279 #ifndef QT_NO_PICTURE
       
   280     picture = 0;
       
   281 #endif
       
   282     align = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextExpandTabs;
       
   283     indent = -1;
       
   284     scaledcontents = false;
       
   285     textLayoutDirty = false;
       
   286     textDirty = false;
       
   287     textformat = Qt::AutoText;
       
   288     control = 0;
       
   289     textInteractionFlags = Qt::LinksAccessibleByMouse;
       
   290     isRichText = false;
       
   291     isTextLabel = false;
       
   292 
       
   293     q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred,
       
   294                                  QSizePolicy::Label));
       
   295 
       
   296 #ifndef QT_NO_CURSOR
       
   297     validCursor = false;
       
   298     onAnchor = false;
       
   299 #endif
       
   300 
       
   301     openExternalLinks = false;
       
   302 
       
   303     setLayoutItemMargins(QStyle::SE_LabelLayoutItem);
       
   304 }
       
   305 
       
   306 
       
   307 /*!
       
   308     \property QLabel::text
       
   309     \brief the label's text
       
   310 
       
   311     If no text has been set this will return an empty string. Setting
       
   312     the text clears any previous content.
       
   313 
       
   314     The text will be interpreted either as plain text or as rich
       
   315     text, depending on the text format setting; see setTextFormat().
       
   316     The default setting is Qt::AutoText; i.e. QLabel will try to
       
   317     auto-detect the format of the text set.
       
   318 
       
   319     If a buddy has been set, the buddy mnemonic key is updated
       
   320     from the new text.
       
   321 
       
   322     Note that QLabel is well-suited to display small rich text
       
   323     documents, such as small documents that get their document
       
   324     specific settings (font, text color, link color) from the label's
       
   325     palette and font properties. For large documents, use QTextEdit
       
   326     in read-only mode instead. QTextEdit can also provide a scroll bar
       
   327     when necessary.
       
   328 
       
   329     \note This function enables mouse tracking if \a text contains rich
       
   330     text.
       
   331 
       
   332     \sa setTextFormat(), setBuddy(), alignment
       
   333 */
       
   334 
       
   335 void QLabel::setText(const QString &text)
       
   336 {
       
   337     Q_D(QLabel);
       
   338     if (d->text == text)
       
   339         return;
       
   340 
       
   341     QTextControl *oldControl = d->control;
       
   342     d->control = 0;
       
   343 
       
   344     d->clearContents();
       
   345     d->text = text;
       
   346     d->isTextLabel = true;
       
   347     d->textDirty = true;
       
   348     d->isRichText = d->textformat == Qt::RichText
       
   349                     || (d->textformat == Qt::AutoText && Qt::mightBeRichText(d->text));
       
   350 
       
   351     d->control = oldControl;
       
   352 
       
   353     if (d->needTextControl()) {
       
   354         d->ensureTextControl();
       
   355     } else {
       
   356         delete d->control;
       
   357         d->control = 0;
       
   358     }
       
   359 
       
   360     if (d->isRichText) {
       
   361         setMouseTracking(true);
       
   362     } else {
       
   363         // Note: mouse tracking not disabled intentionally
       
   364     }
       
   365 
       
   366 #ifndef QT_NO_SHORTCUT
       
   367     if (d->buddy)
       
   368         d->updateShortcut();
       
   369 #endif
       
   370 
       
   371     d->updateLabel();
       
   372 }
       
   373 
       
   374 QString QLabel::text() const
       
   375 {
       
   376     Q_D(const QLabel);
       
   377     return d->text;
       
   378 }
       
   379 
       
   380 /*!
       
   381     Clears any label contents.
       
   382 */
       
   383 
       
   384 void QLabel::clear()
       
   385 {
       
   386     Q_D(QLabel);
       
   387     d->clearContents();
       
   388     d->updateLabel();
       
   389 }
       
   390 
       
   391 /*!
       
   392     \property QLabel::pixmap
       
   393     \brief the label's pixmap
       
   394 
       
   395     If no pixmap has been set this will return 0.
       
   396 
       
   397     Setting the pixmap clears any previous content. The buddy
       
   398     shortcut, if any, is disabled.
       
   399 */
       
   400 void QLabel::setPixmap(const QPixmap &pixmap)
       
   401 {
       
   402     Q_D(QLabel);
       
   403     if (!d->pixmap || d->pixmap->cacheKey() != pixmap.cacheKey()) {
       
   404         d->clearContents();
       
   405         d->pixmap = new QPixmap(pixmap);
       
   406     }
       
   407 
       
   408     if (d->pixmap->depth() == 1 && !d->pixmap->mask())
       
   409         d->pixmap->setMask(*((QBitmap *)d->pixmap));
       
   410 
       
   411     d->updateLabel();
       
   412 }
       
   413 
       
   414 const QPixmap *QLabel::pixmap() const
       
   415 {
       
   416     Q_D(const QLabel);
       
   417     return d->pixmap;
       
   418 }
       
   419 
       
   420 #ifndef QT_NO_PICTURE
       
   421 /*!
       
   422     Sets the label contents to \a picture. Any previous content is
       
   423     cleared.
       
   424 
       
   425     The buddy shortcut, if any, is disabled.
       
   426 
       
   427     \sa picture(), setBuddy()
       
   428 */
       
   429 
       
   430 void QLabel::setPicture(const QPicture &picture)
       
   431 {
       
   432     Q_D(QLabel);
       
   433     d->clearContents();
       
   434     d->picture = new QPicture(picture);
       
   435 
       
   436     d->updateLabel();
       
   437 }
       
   438 #endif // QT_NO_PICTURE
       
   439 
       
   440 /*!
       
   441     Sets the label contents to plain text containing the textual
       
   442     representation of integer \a num. Any previous content is cleared.
       
   443     Does nothing if the integer's string representation is the same as
       
   444     the current contents of the label.
       
   445 
       
   446     The buddy shortcut, if any, is disabled.
       
   447 
       
   448     \sa setText(), QString::setNum(), setBuddy()
       
   449 */
       
   450 
       
   451 void QLabel::setNum(int num)
       
   452 {
       
   453     QString str;
       
   454     str.setNum(num);
       
   455     setText(str);
       
   456 }
       
   457 
       
   458 /*!
       
   459     \overload
       
   460 
       
   461     Sets the label contents to plain text containing the textual
       
   462     representation of double \a num. Any previous content is cleared.
       
   463     Does nothing if the double's string representation is the same as
       
   464     the current contents of the label.
       
   465 
       
   466     The buddy shortcut, if any, is disabled.
       
   467 
       
   468     \sa setText(), QString::setNum(), setBuddy()
       
   469 */
       
   470 
       
   471 void QLabel::setNum(double num)
       
   472 {
       
   473     QString str;
       
   474     str.setNum(num);
       
   475     setText(str);
       
   476 }
       
   477 
       
   478 /*!
       
   479     \property QLabel::alignment
       
   480     \brief the alignment of the label's contents
       
   481 
       
   482     By default, the contents of the label are left-aligned and vertically-centered.
       
   483 
       
   484     \sa text
       
   485 */
       
   486 
       
   487 void QLabel::setAlignment(Qt::Alignment alignment)
       
   488 {
       
   489     Q_D(QLabel);
       
   490     if (alignment == (d->align & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask)))
       
   491         return;
       
   492     d->align = (d->align & ~(Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask))
       
   493                | (alignment & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask));
       
   494 
       
   495     d->updateLabel();
       
   496 }
       
   497 
       
   498 #ifdef QT3_SUPPORT
       
   499 /*!
       
   500     Use setAlignment(Qt::Alignment) instead.
       
   501 
       
   502     If \a alignment specifies text flags as well, use setTextFormat()
       
   503     to set those.
       
   504 */
       
   505 void QLabel::setAlignment(int alignment)
       
   506 {
       
   507     Q_D(QLabel);
       
   508     d->align = alignment & ~(Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask|Qt::TextWordWrap);
       
   509     setAlignment(Qt::Alignment(QFlag(alignment)));
       
   510 }
       
   511 #endif
       
   512 
       
   513 Qt::Alignment QLabel::alignment() const
       
   514 {
       
   515     Q_D(const QLabel);
       
   516     return QFlag(d->align & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask));
       
   517 }
       
   518 
       
   519 
       
   520 /*!
       
   521     \property QLabel::wordWrap
       
   522     \brief the label's word-wrapping policy
       
   523 
       
   524     If this property is true then label text is wrapped where
       
   525     necessary at word-breaks; otherwise it is not wrapped at all.
       
   526 
       
   527     By default, word wrap is disabled.
       
   528 
       
   529     \sa text
       
   530 */
       
   531 void QLabel::setWordWrap(bool on)
       
   532 {
       
   533     Q_D(QLabel);
       
   534     if (on)
       
   535         d->align |= Qt::TextWordWrap;
       
   536     else
       
   537         d->align &= ~Qt::TextWordWrap;
       
   538 
       
   539     d->updateLabel();
       
   540 }
       
   541 
       
   542 bool QLabel::wordWrap() const
       
   543 {
       
   544     Q_D(const QLabel);
       
   545     return d->align & Qt::TextWordWrap;
       
   546 }
       
   547 
       
   548 /*!
       
   549     \property QLabel::indent
       
   550     \brief the label's text indent in pixels
       
   551 
       
   552     If a label displays text, the indent applies to the left edge if
       
   553     alignment() is Qt::AlignLeft, to the right edge if alignment() is
       
   554     Qt::AlignRight, to the top edge if alignment() is Qt::AlignTop, and
       
   555     to to the bottom edge if alignment() is Qt::AlignBottom.
       
   556 
       
   557     If indent is negative, or if no indent has been set, the label
       
   558     computes the effective indent as follows: If frameWidth() is 0,
       
   559     the effective indent becomes 0. If frameWidth() is greater than 0,
       
   560     the effective indent becomes half the width of the "x" character
       
   561     of the widget's current font().
       
   562 
       
   563     By default, the indent is -1, meaning that an effective indent is
       
   564     calculating in the manner described above.
       
   565 
       
   566     \sa alignment, margin, frameWidth(), font()
       
   567 */
       
   568 
       
   569 void QLabel::setIndent(int indent)
       
   570 {
       
   571     Q_D(QLabel);
       
   572     d->indent = indent;
       
   573     d->updateLabel();
       
   574 }
       
   575 
       
   576 int QLabel::indent() const
       
   577 {
       
   578     Q_D(const QLabel);
       
   579     return d->indent;
       
   580 }
       
   581 
       
   582 
       
   583 /*!
       
   584     \property QLabel::margin
       
   585     \brief the width of the margin
       
   586 
       
   587     The margin is the distance between the innermost pixel of the
       
   588     frame and the outermost pixel of contents.
       
   589 
       
   590     The default margin is 0.
       
   591 
       
   592     \sa indent
       
   593 */
       
   594 int QLabel::margin() const
       
   595 {
       
   596     Q_D(const QLabel);
       
   597     return d->margin;
       
   598 }
       
   599 
       
   600 void QLabel::setMargin(int margin)
       
   601 {
       
   602     Q_D(QLabel);
       
   603     if (d->margin == margin)
       
   604         return;
       
   605     d->margin = margin;
       
   606     d->updateLabel();
       
   607 }
       
   608 
       
   609 /*!
       
   610     Returns the size that will be used if the width of the label is \a
       
   611     w. If \a w is -1, the sizeHint() is returned. If \a w is 0 minimumSizeHint() is returned
       
   612 */
       
   613 QSize QLabelPrivate::sizeForWidth(int w) const
       
   614 {
       
   615     Q_Q(const QLabel);
       
   616     if(q->minimumWidth() > 0)
       
   617         w = qMax(w, q->minimumWidth());
       
   618     QSize contentsMargin(leftmargin + rightmargin, topmargin + bottommargin);
       
   619 
       
   620     QRect br;
       
   621 
       
   622     int hextra = 2 * margin;
       
   623     int vextra = hextra;
       
   624     QFontMetrics fm = q->fontMetrics();
       
   625 
       
   626     if (pixmap && !pixmap->isNull())
       
   627         br = pixmap->rect();
       
   628 #ifndef QT_NO_PICTURE
       
   629     else if (picture && !picture->isNull())
       
   630         br = picture->boundingRect();
       
   631 #endif
       
   632 #ifndef QT_NO_MOVIE
       
   633     else if (movie && !movie->currentPixmap().isNull())
       
   634         br = movie->currentPixmap().rect();
       
   635 #endif
       
   636     else if (isTextLabel) {
       
   637         int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align));
       
   638         // Add indentation
       
   639         int m = indent;
       
   640 
       
   641         if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
       
   642             m = fm.width(QLatin1Char('x')) - margin*2;
       
   643         if (m > 0) {
       
   644             if ((align & Qt::AlignLeft) || (align & Qt::AlignRight))
       
   645                 hextra += m;
       
   646             if ((align & Qt::AlignTop) || (align & Qt::AlignBottom))
       
   647                 vextra += m;
       
   648         }
       
   649 
       
   650         if (control) {
       
   651             ensureTextLayouted();
       
   652             const qreal oldTextWidth = control->textWidth();
       
   653             // Calculate the length of document if w is the width
       
   654             if (align & Qt::TextWordWrap) {
       
   655                 if (w >= 0) {
       
   656                     w = qMax(w-hextra-contentsMargin.width(), 0); // strip margin and indent
       
   657                     control->setTextWidth(w);
       
   658                 } else {
       
   659                     control->adjustSize();
       
   660                 }
       
   661             } else {
       
   662                 control->setTextWidth(-1);
       
   663             }
       
   664             br = QRect(QPoint(0, 0), control->size().toSize());
       
   665 
       
   666             // restore state
       
   667             control->setTextWidth(oldTextWidth);
       
   668         } else {
       
   669             // Turn off center alignment in order to avoid rounding errors for centering,
       
   670             // since centering involves a division by 2. At the end, all we want is the size.
       
   671             int flags = align & ~(Qt::AlignVCenter | Qt::AlignHCenter);
       
   672             if (hasShortcut) {
       
   673                 flags |= Qt::TextShowMnemonic;
       
   674                 QStyleOption opt;
       
   675                 opt.initFrom(q);
       
   676                 if (!q->style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, q))
       
   677                     flags |= Qt::TextHideMnemonic;
       
   678             }
       
   679 
       
   680             bool tryWidth = (w < 0) && (align & Qt::TextWordWrap);
       
   681             if (tryWidth)
       
   682                 w = fm.averageCharWidth() * 80;
       
   683             else if (w < 0)
       
   684                 w = 2000;
       
   685             w -= (hextra + contentsMargin.width());
       
   686             br = fm.boundingRect(0, 0, w ,2000, flags, text);
       
   687             if (tryWidth && br.height() < 4*fm.lineSpacing() && br.width() > w/2)
       
   688                 br = fm.boundingRect(0, 0, w/2, 2000, flags, text);
       
   689             if (tryWidth && br.height() < 2*fm.lineSpacing() && br.width() > w/4)
       
   690                 br = fm.boundingRect(0, 0, w/4, 2000, flags, text);
       
   691         }
       
   692     } else {
       
   693         br = QRect(QPoint(0, 0), QSize(fm.averageCharWidth(), fm.lineSpacing()));
       
   694     }
       
   695 
       
   696     const QSize contentsSize(br.width() + hextra, br.height() + vextra);
       
   697     return (contentsSize + contentsMargin).expandedTo(q->minimumSize());
       
   698 }
       
   699 
       
   700 
       
   701 /*!
       
   702   \reimp
       
   703 */
       
   704 
       
   705 int QLabel::heightForWidth(int w) const
       
   706 {
       
   707     Q_D(const QLabel);
       
   708     if (d->isTextLabel)
       
   709         return d->sizeForWidth(w).height();
       
   710     return QWidget::heightForWidth(w);
       
   711 }
       
   712 
       
   713 /*!
       
   714     \property QLabel::openExternalLinks
       
   715     \since 4.2
       
   716 
       
   717     Specifies whether QLabel should automatically open links using
       
   718     QDesktopServices::openUrl() instead of emitting the
       
   719     linkActivated() signal.
       
   720 
       
   721     \bold{Note:} The textInteractionFlags set on the label need to include
       
   722     either LinksAccessibleByMouse or LinksAccessibleByKeyboard.
       
   723 
       
   724     The default value is false.
       
   725 
       
   726     \sa textInteractionFlags()
       
   727 */
       
   728 bool QLabel::openExternalLinks() const
       
   729 {
       
   730     Q_D(const QLabel);
       
   731     return d->openExternalLinks;
       
   732 }
       
   733 
       
   734 void QLabel::setOpenExternalLinks(bool open)
       
   735 {
       
   736     Q_D(QLabel);
       
   737     d->openExternalLinks = open;
       
   738     if (d->control)
       
   739         d->control->setOpenExternalLinks(open);
       
   740 }
       
   741 
       
   742 /*!
       
   743     \property QLabel::textInteractionFlags
       
   744     \since 4.2
       
   745 
       
   746     Specifies how the label should interact with user input if it displays text.
       
   747 
       
   748     If the flags contain Qt::LinksAccessibleByKeyboard the focus policy is also
       
   749     automatically set to Qt::StrongFocus. If Qt::TextSelectableByKeyboard is set
       
   750     then the focus policy is set to Qt::ClickFocus.
       
   751 
       
   752     The default value is Qt::LinksAccessibleByMouse.
       
   753 */
       
   754 void QLabel::setTextInteractionFlags(Qt::TextInteractionFlags flags)
       
   755 {
       
   756     Q_D(QLabel);
       
   757     if (d->textInteractionFlags == flags)
       
   758         return;
       
   759     d->textInteractionFlags = flags;
       
   760     if (flags & Qt::LinksAccessibleByKeyboard)
       
   761         setFocusPolicy(Qt::StrongFocus);
       
   762     else if (flags & (Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse))
       
   763         setFocusPolicy(Qt::ClickFocus);
       
   764     else
       
   765         setFocusPolicy(Qt::NoFocus);
       
   766 
       
   767     if (d->needTextControl()) {
       
   768         d->ensureTextControl();
       
   769     } else {
       
   770         delete d->control;
       
   771         d->control = 0;
       
   772     }
       
   773 
       
   774     if (d->control)
       
   775         d->control->setTextInteractionFlags(d->textInteractionFlags);
       
   776 }
       
   777 
       
   778 Qt::TextInteractionFlags QLabel::textInteractionFlags() const
       
   779 {
       
   780     Q_D(const QLabel);
       
   781     return d->textInteractionFlags;
       
   782 }
       
   783 
       
   784 /*!\reimp
       
   785 */
       
   786 QSize QLabel::sizeHint() const
       
   787 {
       
   788     Q_D(const QLabel);
       
   789     if (!d->valid_hints)
       
   790         (void) QLabel::minimumSizeHint();
       
   791     return d->sh;
       
   792 }
       
   793 
       
   794 /*!
       
   795   \reimp
       
   796 */
       
   797 QSize QLabel::minimumSizeHint() const
       
   798 {
       
   799     Q_D(const QLabel);
       
   800     if (d->valid_hints) {
       
   801         if (d->sizePolicy == sizePolicy())
       
   802             return d->msh;
       
   803     }
       
   804 
       
   805     ensurePolished();
       
   806     d->valid_hints = true;
       
   807     d->sh = d->sizeForWidth(-1); // wrap ? golden ratio : min doc size
       
   808     QSize msh(-1, -1);
       
   809 
       
   810     if (!d->isTextLabel) {
       
   811         msh = d->sh;
       
   812     } else {
       
   813         msh.rheight() = d->sizeForWidth(QWIDGETSIZE_MAX).height(); // height for one line
       
   814         msh.rwidth() = d->sizeForWidth(0).width(); // wrap ? size of biggest word : min doc size
       
   815         if (d->sh.height() < msh.height())
       
   816             msh.rheight() = d->sh.height();
       
   817     }
       
   818     d->msh = msh;
       
   819     d->sizePolicy = sizePolicy();
       
   820     return msh;
       
   821 }
       
   822 
       
   823 /*!\reimp
       
   824 */
       
   825 void QLabel::mousePressEvent(QMouseEvent *ev)
       
   826 {
       
   827     Q_D(QLabel);
       
   828     d->sendControlEvent(ev);
       
   829 }
       
   830 
       
   831 /*!\reimp
       
   832 */
       
   833 void QLabel::mouseMoveEvent(QMouseEvent *ev)
       
   834 {
       
   835     Q_D(QLabel);
       
   836     d->sendControlEvent(ev);
       
   837 }
       
   838 
       
   839 /*!\reimp
       
   840 */
       
   841 void QLabel::mouseReleaseEvent(QMouseEvent *ev)
       
   842 {
       
   843     Q_D(QLabel);
       
   844     d->sendControlEvent(ev);
       
   845 }
       
   846 
       
   847 /*!\reimp
       
   848 */
       
   849 void QLabel::contextMenuEvent(QContextMenuEvent *ev)
       
   850 {
       
   851 #ifdef QT_NO_CONTEXTMENU
       
   852     Q_UNUSED(ev);
       
   853 #else
       
   854     Q_D(QLabel);
       
   855     if (!d->isTextLabel) {
       
   856         ev->ignore();
       
   857         return;
       
   858     }
       
   859     QMenu *menu = d->createStandardContextMenu(ev->pos());
       
   860     if (!menu) {
       
   861         ev->ignore();
       
   862         return;
       
   863     }
       
   864     ev->accept();
       
   865     menu->exec(ev->globalPos());
       
   866     delete menu;
       
   867 #endif
       
   868 }
       
   869 
       
   870 /*!
       
   871     \reimp
       
   872 */
       
   873 void QLabel::focusInEvent(QFocusEvent *ev)
       
   874 {
       
   875     Q_D(QLabel);
       
   876     if (d->isTextLabel) {
       
   877         d->ensureTextControl();
       
   878         d->sendControlEvent(ev);
       
   879     }
       
   880     QFrame::focusInEvent(ev);
       
   881 }
       
   882 
       
   883 /*!
       
   884     \reimp
       
   885 */
       
   886 void QLabel::focusOutEvent(QFocusEvent *ev)
       
   887 {
       
   888     Q_D(QLabel);
       
   889     if (d->control) {
       
   890         d->sendControlEvent(ev);
       
   891         QTextCursor cursor = d->control->textCursor();
       
   892         Qt::FocusReason reason = ev->reason();
       
   893         if (reason != Qt::ActiveWindowFocusReason
       
   894             && reason != Qt::PopupFocusReason
       
   895             && cursor.hasSelection()) {
       
   896             cursor.clearSelection();
       
   897             d->control->setTextCursor(cursor);
       
   898         }
       
   899     }
       
   900 
       
   901     QFrame::focusOutEvent(ev);
       
   902 }
       
   903 
       
   904 /*!\reimp
       
   905 */
       
   906 bool QLabel::focusNextPrevChild(bool next)
       
   907 {
       
   908     Q_D(QLabel);
       
   909     if (d->control && d->control->setFocusToNextOrPreviousAnchor(next))
       
   910         return true;
       
   911     return QFrame::focusNextPrevChild(next);
       
   912 }
       
   913 
       
   914 /*!\reimp
       
   915 */
       
   916 void QLabel::keyPressEvent(QKeyEvent *ev)
       
   917 {
       
   918     Q_D(QLabel);
       
   919     d->sendControlEvent(ev);
       
   920 }
       
   921 
       
   922 /*!\reimp
       
   923 */
       
   924 bool QLabel::event(QEvent *e)
       
   925 {
       
   926     Q_D(QLabel);
       
   927     QEvent::Type type = e->type();
       
   928 
       
   929 #ifndef QT_NO_SHORTCUT
       
   930     if (type == QEvent::Shortcut) {
       
   931         QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
       
   932         if (se->shortcutId() == d->shortcutId) {
       
   933             QWidget * w = d->buddy;
       
   934             QAbstractButton *button = qobject_cast<QAbstractButton *>(w);
       
   935             if (w->focusPolicy() != Qt::NoFocus)
       
   936                 w->setFocus(Qt::ShortcutFocusReason);
       
   937             if (button && !se->isAmbiguous())
       
   938                 button->animateClick();
       
   939             else
       
   940                 window()->setAttribute(Qt::WA_KeyboardFocusChange);
       
   941             return true;
       
   942         }
       
   943     } else
       
   944 #endif
       
   945     if (type == QEvent::Resize) {
       
   946         if (d->control)
       
   947             d->textLayoutDirty = true;
       
   948     } else if (e->type() == QEvent::StyleChange
       
   949 #ifdef Q_WS_MAC
       
   950                || e->type() == QEvent::MacSizeChange
       
   951 #endif
       
   952                ) {
       
   953         d->setLayoutItemMargins(QStyle::SE_LabelLayoutItem);
       
   954         d->updateLabel();
       
   955     }
       
   956 
       
   957     return QFrame::event(e);
       
   958 }
       
   959 
       
   960 /*!\reimp
       
   961 */
       
   962 void QLabel::paintEvent(QPaintEvent *)
       
   963 {
       
   964     Q_D(QLabel);
       
   965     QStyle *style = QWidget::style();
       
   966     QPainter painter(this);
       
   967     drawFrame(&painter);
       
   968     QRect cr = contentsRect();
       
   969     cr.adjust(d->margin, d->margin, -d->margin, -d->margin);
       
   970     int align = QStyle::visualAlignment(layoutDirection(), QFlag(d->align));
       
   971 
       
   972 #ifndef QT_NO_MOVIE
       
   973     if (d->movie) {
       
   974         if (d->scaledcontents)
       
   975             style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap().scaled(cr.size()));
       
   976         else
       
   977             style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap());
       
   978     }
       
   979     else
       
   980 #endif
       
   981     if (d->isTextLabel) {
       
   982         QRectF lr = d->layoutRect();
       
   983         QStyleOption opt;
       
   984         opt.initFrom(this);
       
   985 #ifndef QT_NO_STYLE_STYLESHEET
       
   986         if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) {
       
   987             cssStyle->styleSheetPalette(this, &opt, &opt.palette);
       
   988         }
       
   989 #endif
       
   990         if (d->control) {
       
   991 #ifndef QT_NO_SHORTCUT
       
   992             const bool underline = (bool)style->styleHint(QStyle::SH_UnderlineShortcut, 0, this, 0);
       
   993             if (d->shortcutId != 0
       
   994                 && underline != d->shortcutCursor.charFormat().fontUnderline()) {
       
   995                 QTextCharFormat fmt;
       
   996                 fmt.setFontUnderline(underline);
       
   997                 d->shortcutCursor.mergeCharFormat(fmt);
       
   998             }
       
   999 #endif
       
  1000             d->ensureTextLayouted();
       
  1001 
       
  1002             QAbstractTextDocumentLayout::PaintContext context;
       
  1003             if (!isEnabled() && !d->control &&
       
  1004                 // We cannot support etched for rich text controls because custom
       
  1005                 // colors and links will override the light palette
       
  1006                 style->styleHint(QStyle::SH_EtchDisabledText, &opt, this)) {
       
  1007                 context.palette = opt.palette;
       
  1008                 context.palette.setColor(QPalette::Text, context.palette.light().color());
       
  1009                 painter.save();
       
  1010                 painter.translate(lr.x() + 1, lr.y() + 1);
       
  1011                 painter.setClipRect(lr.translated(-lr.x() - 1, -lr.y() - 1));
       
  1012                 QAbstractTextDocumentLayout *layout = d->control->document()->documentLayout();
       
  1013                 layout->draw(&painter, context);
       
  1014                 painter.restore();
       
  1015             }
       
  1016 
       
  1017             // Adjust the palette
       
  1018             context.palette = opt.palette;
       
  1019 
       
  1020             if (foregroundRole() != QPalette::Text && isEnabled())
       
  1021                 context.palette.setColor(QPalette::Text, context.palette.color(foregroundRole()));
       
  1022 
       
  1023             painter.save();
       
  1024             painter.translate(lr.topLeft());
       
  1025             painter.setClipRect(lr.translated(-lr.x(), -lr.y()));
       
  1026             d->control->setPalette(context.palette);
       
  1027             d->control->drawContents(&painter, QRectF(), this);
       
  1028             painter.restore();
       
  1029         } else {
       
  1030             int flags = align;
       
  1031             if (d->hasShortcut) {
       
  1032                 flags |= Qt::TextShowMnemonic;
       
  1033                 if (!style->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
       
  1034                     flags |= Qt::TextHideMnemonic;
       
  1035             }
       
  1036             style->drawItemText(&painter, lr.toRect(), flags, opt.palette, isEnabled(), d->text, foregroundRole());
       
  1037         }
       
  1038     } else
       
  1039 #ifndef QT_NO_PICTURE
       
  1040     if (d->picture) {
       
  1041         QRect br = d->picture->boundingRect();
       
  1042         int rw = br.width();
       
  1043         int rh = br.height();
       
  1044         if (d->scaledcontents) {
       
  1045             painter.save();
       
  1046             painter.translate(cr.x(), cr.y());
       
  1047             painter.scale((double)cr.width()/rw, (double)cr.height()/rh);
       
  1048             painter.drawPicture(-br.x(), -br.y(), *d->picture);
       
  1049             painter.restore();
       
  1050         } else {
       
  1051             int xo = 0;
       
  1052             int yo = 0;
       
  1053             if (align & Qt::AlignVCenter)
       
  1054                 yo = (cr.height()-rh)/2;
       
  1055             else if (align & Qt::AlignBottom)
       
  1056                 yo = cr.height()-rh;
       
  1057             if (align & Qt::AlignRight)
       
  1058                 xo = cr.width()-rw;
       
  1059             else if (align & Qt::AlignHCenter)
       
  1060                 xo = (cr.width()-rw)/2;
       
  1061             painter.drawPicture(cr.x()+xo-br.x(), cr.y()+yo-br.y(), *d->picture);
       
  1062         }
       
  1063     } else
       
  1064 #endif
       
  1065     if (d->pixmap && !d->pixmap->isNull()) {
       
  1066         QPixmap pix;
       
  1067         if (d->scaledcontents) {
       
  1068             if (!d->scaledpixmap || d->scaledpixmap->size() != cr.size()) {
       
  1069                 if (!d->cachedimage)
       
  1070                     d->cachedimage = new QImage(d->pixmap->toImage());
       
  1071                 delete d->scaledpixmap;
       
  1072                 d->scaledpixmap = new QPixmap(QPixmap::fromImage(d->cachedimage->scaled(cr.size(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)));
       
  1073             }
       
  1074             pix = *d->scaledpixmap;
       
  1075         } else
       
  1076             pix = *d->pixmap;
       
  1077         QStyleOption opt;
       
  1078         opt.initFrom(this);
       
  1079         if (!isEnabled())
       
  1080             pix = style->generatedIconPixmap(QIcon::Disabled, pix, &opt);
       
  1081         style->drawItemPixmap(&painter, cr, align, pix);
       
  1082     }
       
  1083 }
       
  1084 
       
  1085 
       
  1086 /*!
       
  1087     Updates the label, but not the frame.
       
  1088 */
       
  1089 
       
  1090 void QLabelPrivate::updateLabel()
       
  1091 {
       
  1092     Q_Q(QLabel);
       
  1093     valid_hints = false;
       
  1094 
       
  1095     if (isTextLabel) {
       
  1096         QSizePolicy policy = q->sizePolicy();
       
  1097         const bool wrap = align & Qt::TextWordWrap;
       
  1098         policy.setHeightForWidth(wrap);
       
  1099         if (policy != q->sizePolicy())  // ### should be replaced by WA_WState_OwnSizePolicy idiom
       
  1100             q->setSizePolicy(policy);
       
  1101         textLayoutDirty = true;
       
  1102     }
       
  1103     q->updateGeometry();
       
  1104     q->update(q->contentsRect());
       
  1105 }
       
  1106 
       
  1107 #ifndef QT_NO_SHORTCUT
       
  1108 /*!
       
  1109     Sets this label's buddy to \a buddy.
       
  1110 
       
  1111     When the user presses the shortcut key indicated by this label,
       
  1112     the keyboard focus is transferred to the label's buddy widget.
       
  1113 
       
  1114     The buddy mechanism is only available for QLabels that contain
       
  1115     text in which one character is prefixed with an ampersand, '&'.
       
  1116     This character is set as the shortcut key. See the \l
       
  1117     QKeySequence::mnemonic() documentation for details (to display an
       
  1118     actual ampersand, use '&&').
       
  1119 
       
  1120     In a dialog, you might create two data entry widgets and a label
       
  1121     for each, and set up the geometry layout so each label is just to
       
  1122     the left of its data entry widget (its "buddy"), for example:
       
  1123     \snippet doc/src/snippets/code/src_gui_widgets_qlabel.cpp 2
       
  1124 
       
  1125     With the code above, the focus jumps to the Name field when the
       
  1126     user presses Alt+N, and to the Phone field when the user presses
       
  1127     Alt+P.
       
  1128 
       
  1129     To unset a previously set buddy, call this function with \a buddy
       
  1130     set to 0.
       
  1131 
       
  1132     \sa buddy(), setText(), QShortcut, setAlignment()
       
  1133 */
       
  1134 
       
  1135 void QLabel::setBuddy(QWidget *buddy)
       
  1136 {
       
  1137     Q_D(QLabel);
       
  1138     d->buddy = buddy;
       
  1139     if (d->isTextLabel) {
       
  1140         if (d->shortcutId)
       
  1141             releaseShortcut(d->shortcutId);
       
  1142         d->shortcutId = 0;
       
  1143         d->textDirty = true;
       
  1144         if (buddy)
       
  1145             d->updateShortcut(); // grab new shortcut
       
  1146         d->updateLabel();
       
  1147     }
       
  1148 }
       
  1149 
       
  1150 
       
  1151 /*!
       
  1152     Returns this label's buddy, or 0 if no buddy is currently set.
       
  1153 
       
  1154     \sa setBuddy()
       
  1155 */
       
  1156 
       
  1157 QWidget * QLabel::buddy() const
       
  1158 {
       
  1159     Q_D(const QLabel);
       
  1160     return d->buddy;
       
  1161 }
       
  1162 
       
  1163 void QLabelPrivate::updateShortcut()
       
  1164 {
       
  1165     Q_Q(QLabel);
       
  1166     Q_ASSERT(shortcutId == 0);
       
  1167     // Introduce an extra boolean to indicate the presence of a shortcut in the
       
  1168     // text. We cannot use the shortcutId itself because on the mac mnemonics are
       
  1169     // off by default, so QKeySequence::mnemonic always returns an empty sequence.
       
  1170     // But then we do want to hide the ampersands, so we can't use shortcutId.
       
  1171     hasShortcut = false;
       
  1172 
       
  1173     if (control) {
       
  1174         ensureTextPopulated();
       
  1175         // Underline the first character that follows an ampersand
       
  1176         shortcutCursor = control->document()->find(QLatin1String("&"));
       
  1177         if (shortcutCursor.isNull())
       
  1178             return;
       
  1179         hasShortcut = true;
       
  1180         shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
       
  1181         shortcutCursor.deleteChar(); // remove the ampersand
       
  1182         shortcutCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
       
  1183     } else {
       
  1184         if (!text.contains(QLatin1Char('&')))
       
  1185             return;
       
  1186         hasShortcut = true;
       
  1187         shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
       
  1188     }
       
  1189 }
       
  1190 
       
  1191 #endif // QT_NO_SHORTCUT
       
  1192 
       
  1193 #ifndef QT_NO_MOVIE
       
  1194 void QLabelPrivate::_q_movieUpdated(const QRect& rect)
       
  1195 {
       
  1196     Q_Q(QLabel);
       
  1197     if (movie && movie->isValid()) {
       
  1198         QRect r;
       
  1199         if (scaledcontents) {
       
  1200             QRect cr = q->contentsRect();
       
  1201             QRect pixmapRect(cr.topLeft(), movie->currentPixmap().size());
       
  1202             if (pixmapRect.isEmpty())
       
  1203                 return;
       
  1204             r.setRect(cr.left(), cr.top(),
       
  1205                       (rect.width() * cr.width()) / pixmapRect.width(),
       
  1206                       (rect.height() * cr.height()) / pixmapRect.height());
       
  1207         } else {
       
  1208             r = q->style()->itemPixmapRect(q->contentsRect(), align, movie->currentPixmap());
       
  1209             r.translate(rect.x(), rect.y());
       
  1210             r.setWidth(qMin(r.width(), rect.width()));
       
  1211             r.setHeight(qMin(r.height(), rect.height()));
       
  1212         }
       
  1213         q->update(r);
       
  1214     }
       
  1215 }
       
  1216 
       
  1217 void QLabelPrivate::_q_movieResized(const QSize& size)
       
  1218 {
       
  1219     Q_Q(QLabel);
       
  1220     q->update(); //we need to refresh the whole background in case the new size is smaler
       
  1221     valid_hints = false;
       
  1222     _q_movieUpdated(QRect(QPoint(0,0), size));
       
  1223     q->updateGeometry();
       
  1224 }
       
  1225 
       
  1226 /*!
       
  1227     Sets the label contents to \a movie. Any previous content is
       
  1228     cleared. The label does NOT take ownership of the movie.
       
  1229 
       
  1230     The buddy shortcut, if any, is disabled.
       
  1231 
       
  1232     \sa movie(), setBuddy()
       
  1233 */
       
  1234 
       
  1235 void QLabel::setMovie(QMovie *movie)
       
  1236 {
       
  1237     Q_D(QLabel);
       
  1238     d->clearContents();
       
  1239 
       
  1240     if (!movie)
       
  1241         return;
       
  1242 
       
  1243     d->movie = movie;
       
  1244     connect(movie, SIGNAL(resized(QSize)), this, SLOT(_q_movieResized(QSize)));
       
  1245     connect(movie, SIGNAL(updated(QRect)), this, SLOT(_q_movieUpdated(QRect)));
       
  1246 
       
  1247     // Assume that if the movie is running,
       
  1248     // resize/update signals will come soon enough
       
  1249     if (movie->state() != QMovie::Running)
       
  1250         d->updateLabel();
       
  1251 }
       
  1252 
       
  1253 #endif // QT_NO_MOVIE
       
  1254 
       
  1255 /*!
       
  1256   \internal
       
  1257 
       
  1258   Clears any contents, without updating/repainting the label.
       
  1259 */
       
  1260 
       
  1261 void QLabelPrivate::clearContents()
       
  1262 {
       
  1263     delete control;
       
  1264     control = 0;
       
  1265     isTextLabel = false;
       
  1266     hasShortcut = false;
       
  1267 
       
  1268 #ifndef QT_NO_PICTURE
       
  1269     delete picture;
       
  1270     picture = 0;
       
  1271 #endif
       
  1272     delete scaledpixmap;
       
  1273     scaledpixmap = 0;
       
  1274     delete cachedimage;
       
  1275     cachedimage = 0;
       
  1276     delete pixmap;
       
  1277     pixmap = 0;
       
  1278 
       
  1279     text.clear();
       
  1280     Q_Q(QLabel);
       
  1281 #ifndef QT_NO_SHORTCUT
       
  1282     if (shortcutId)
       
  1283         q->releaseShortcut(shortcutId);
       
  1284     shortcutId = 0;
       
  1285 #endif
       
  1286 #ifndef QT_NO_MOVIE
       
  1287     if (movie) {
       
  1288         QObject::disconnect(movie, SIGNAL(resized(QSize)), q, SLOT(_q_movieResized(QSize)));
       
  1289         QObject::disconnect(movie, SIGNAL(updated(QRect)), q, SLOT(_q_movieUpdated(QRect)));
       
  1290     }
       
  1291     movie = 0;
       
  1292 #endif
       
  1293 #ifndef QT_NO_CURSOR
       
  1294     if (onAnchor) {
       
  1295         if (validCursor)
       
  1296             q->setCursor(cursor);
       
  1297         else
       
  1298             q->unsetCursor();
       
  1299     }
       
  1300     validCursor = false;
       
  1301     onAnchor = false;
       
  1302 #endif
       
  1303 }
       
  1304 
       
  1305 
       
  1306 #ifndef QT_NO_MOVIE
       
  1307 
       
  1308 /*!
       
  1309     Returns a pointer to the label's movie, or 0 if no movie has been
       
  1310     set.
       
  1311 
       
  1312     \sa setMovie()
       
  1313 */
       
  1314 
       
  1315 QMovie *QLabel::movie() const
       
  1316 {
       
  1317     Q_D(const QLabel);
       
  1318     return d->movie;
       
  1319 }
       
  1320 
       
  1321 #endif  // QT_NO_MOVIE
       
  1322 
       
  1323 /*!
       
  1324     \property QLabel::textFormat
       
  1325     \brief the label's text format
       
  1326 
       
  1327     See the Qt::TextFormat enum for an explanation of the possible
       
  1328     options.
       
  1329 
       
  1330     The default format is Qt::AutoText.
       
  1331 
       
  1332     \sa text()
       
  1333 */
       
  1334 
       
  1335 Qt::TextFormat QLabel::textFormat() const
       
  1336 {
       
  1337     Q_D(const QLabel);
       
  1338     return d->textformat;
       
  1339 }
       
  1340 
       
  1341 void QLabel::setTextFormat(Qt::TextFormat format)
       
  1342 {
       
  1343     Q_D(QLabel);
       
  1344     if (format != d->textformat) {
       
  1345         d->textformat = format;
       
  1346         QString t = d->text;
       
  1347         if (!t.isNull()) {
       
  1348             d->text.clear();
       
  1349             setText(t);
       
  1350         }
       
  1351     }
       
  1352 }
       
  1353 
       
  1354 /*!
       
  1355   \reimp
       
  1356 */
       
  1357 void QLabel::changeEvent(QEvent *ev)
       
  1358 {
       
  1359     Q_D(QLabel);
       
  1360     if(ev->type() == QEvent::FontChange || ev->type() == QEvent::ApplicationFontChange) {
       
  1361         if (d->isTextLabel) {
       
  1362             if (d->control)
       
  1363                 d->control->document()->setDefaultFont(font());
       
  1364             d->updateLabel();
       
  1365         }
       
  1366     } else if (ev->type() == QEvent::PaletteChange && d->control) {
       
  1367         d->control->setPalette(palette());
       
  1368     } else if (ev->type() == QEvent::ContentsRectChange) {
       
  1369         d->updateLabel();
       
  1370     } else if (ev->type() == QEvent::LayoutDirectionChange) {
       
  1371         if (d->isTextLabel && d->control) {
       
  1372             d->sendControlEvent(ev);
       
  1373         }
       
  1374     }
       
  1375     QFrame::changeEvent(ev);
       
  1376 }
       
  1377 
       
  1378 /*!
       
  1379     \property QLabel::scaledContents
       
  1380     \brief whether the label will scale its contents to fill all
       
  1381     available space.
       
  1382 
       
  1383     When enabled and the label shows a pixmap, it will scale the
       
  1384     pixmap to fill the available space.
       
  1385 
       
  1386     This property's default is false.
       
  1387 */
       
  1388 bool QLabel::hasScaledContents() const
       
  1389 {
       
  1390     Q_D(const QLabel);
       
  1391     return d->scaledcontents;
       
  1392 }
       
  1393 
       
  1394 void QLabel::setScaledContents(bool enable)
       
  1395 {
       
  1396     Q_D(QLabel);
       
  1397     if ((bool)d->scaledcontents == enable)
       
  1398         return;
       
  1399     d->scaledcontents = enable;
       
  1400     if (!enable) {
       
  1401         delete d->scaledpixmap;
       
  1402         d->scaledpixmap = 0;
       
  1403         delete d->cachedimage;
       
  1404         d->cachedimage = 0;
       
  1405     }
       
  1406     update(contentsRect());
       
  1407 }
       
  1408 
       
  1409 
       
  1410 /*!
       
  1411     \fn void QLabel::setAlignment(Qt::AlignmentFlag flag)
       
  1412     \internal
       
  1413 
       
  1414     Without this function, a call to e.g. setAlignment(Qt::AlignTop)
       
  1415     results in the \c QT3_SUPPORT function setAlignment(int) being called,
       
  1416     rather than setAlignment(Qt::Alignment).
       
  1417 */
       
  1418 
       
  1419 // Returns the rect that is available for us to draw the document
       
  1420 QRect QLabelPrivate::documentRect() const
       
  1421 {
       
  1422     Q_Q(const QLabel);
       
  1423     Q_ASSERT_X(isTextLabel, "documentRect", "document rect called for label that is not a text label!");
       
  1424     QRect cr = q->contentsRect();
       
  1425     cr.adjust(margin, margin, -margin, -margin);
       
  1426     const int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align));
       
  1427     int m = indent;
       
  1428     if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
       
  1429         m = q->fontMetrics().width(QLatin1Char('x')) / 2 - margin;
       
  1430     if (m > 0) {
       
  1431         if (align & Qt::AlignLeft)
       
  1432             cr.setLeft(cr.left() + m);
       
  1433         if (align & Qt::AlignRight)
       
  1434             cr.setRight(cr.right() - m);
       
  1435         if (align & Qt::AlignTop)
       
  1436             cr.setTop(cr.top() + m);
       
  1437         if (align & Qt::AlignBottom)
       
  1438             cr.setBottom(cr.bottom() - m);
       
  1439     }
       
  1440     return cr;
       
  1441 }
       
  1442 
       
  1443 void QLabelPrivate::ensureTextPopulated() const
       
  1444 {
       
  1445     if (!textDirty)
       
  1446         return;
       
  1447     if (control) {
       
  1448         QTextDocument *doc = control->document();
       
  1449         if (textDirty) {
       
  1450 #ifndef QT_NO_TEXTHTMLPARSER
       
  1451             if (isRichText)
       
  1452                 doc->setHtml(text);
       
  1453             else
       
  1454                 doc->setPlainText(text);
       
  1455 #else
       
  1456             doc->setPlainText(text);
       
  1457 #endif
       
  1458             doc->setUndoRedoEnabled(false);
       
  1459         }
       
  1460     }
       
  1461     textDirty = false;
       
  1462 }
       
  1463 
       
  1464 void QLabelPrivate::ensureTextLayouted() const
       
  1465 {
       
  1466     if (!textLayoutDirty)
       
  1467         return;
       
  1468     ensureTextPopulated();
       
  1469     Q_Q(const QLabel);
       
  1470     if (control) {
       
  1471         QTextDocument *doc = control->document();
       
  1472         QTextOption opt = doc->defaultTextOption();
       
  1473 
       
  1474         opt.setAlignment(QFlag(this->align));
       
  1475 
       
  1476         if (this->align & Qt::TextWordWrap)
       
  1477             opt.setWrapMode(QTextOption::WordWrap);
       
  1478         else
       
  1479             opt.setWrapMode(QTextOption::ManualWrap);
       
  1480 
       
  1481         opt.setTextDirection(q->layoutDirection());
       
  1482 
       
  1483         doc->setDefaultTextOption(opt);
       
  1484 
       
  1485         QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
       
  1486         fmt.setMargin(0);
       
  1487         doc->rootFrame()->setFrameFormat(fmt);
       
  1488         doc->setTextWidth(documentRect().width());
       
  1489     }
       
  1490     textLayoutDirty = false;
       
  1491 }
       
  1492 
       
  1493 void QLabelPrivate::ensureTextControl() const
       
  1494 {
       
  1495     Q_Q(const QLabel);
       
  1496     if (!isTextLabel)
       
  1497         return;
       
  1498     if (!control) {
       
  1499         control = new QTextControl(const_cast<QLabel *>(q));
       
  1500         control->document()->setUndoRedoEnabled(false);
       
  1501         control->document()->setDefaultFont(q->font());
       
  1502         control->setTextInteractionFlags(textInteractionFlags);
       
  1503         control->setOpenExternalLinks(openExternalLinks);
       
  1504         control->setPalette(q->palette());
       
  1505         control->setFocus(q->hasFocus());
       
  1506         QObject::connect(control, SIGNAL(updateRequest(QRectF)),
       
  1507                          q, SLOT(update()));
       
  1508         QObject::connect(control, SIGNAL(linkHovered(QString)),
       
  1509                          q, SLOT(_q_linkHovered(QString)));
       
  1510         QObject::connect(control, SIGNAL(linkActivated(QString)),
       
  1511                          q, SIGNAL(linkActivated(QString)));
       
  1512         textLayoutDirty = true;
       
  1513         textDirty = true;
       
  1514     }
       
  1515 }
       
  1516 
       
  1517 void QLabelPrivate::sendControlEvent(QEvent *e)
       
  1518 {
       
  1519     Q_Q(QLabel);
       
  1520     if (!isTextLabel || !control || textInteractionFlags == Qt::NoTextInteraction) {
       
  1521         e->ignore();
       
  1522         return;
       
  1523     }
       
  1524     control->processEvent(e, -layoutRect().topLeft(), q);
       
  1525 }
       
  1526 
       
  1527 void QLabelPrivate::_q_linkHovered(const QString &anchor)
       
  1528 {
       
  1529     Q_Q(QLabel);
       
  1530 #ifndef QT_NO_CURSOR
       
  1531     if (anchor.isEmpty()) { // restore cursor
       
  1532         if (validCursor)
       
  1533             q->setCursor(cursor);
       
  1534         else
       
  1535             q->unsetCursor();
       
  1536         onAnchor = false;
       
  1537     } else if (!onAnchor) {
       
  1538         validCursor = q->testAttribute(Qt::WA_SetCursor);
       
  1539         if (validCursor) {
       
  1540             cursor = q->cursor();
       
  1541         }
       
  1542         q->setCursor(Qt::PointingHandCursor);
       
  1543         onAnchor = true;
       
  1544     }
       
  1545 #endif
       
  1546     emit q->linkHovered(anchor);
       
  1547 }
       
  1548 
       
  1549 // Return the layout rect - this is the rect that is given to the layout painting code
       
  1550 // This may be different from the document rect since vertical alignment is not
       
  1551 // done by the text layout code
       
  1552 QRectF QLabelPrivate::layoutRect() const
       
  1553 {
       
  1554     QRectF cr = documentRect();
       
  1555     if (!control)
       
  1556         return cr;
       
  1557     ensureTextLayouted();
       
  1558     // Caculate y position manually
       
  1559     qreal rh = control->document()->documentLayout()->documentSize().height();
       
  1560     qreal yo = 0;
       
  1561     if (align & Qt::AlignVCenter)
       
  1562         yo = qMax((cr.height()-rh)/2, qreal(0));
       
  1563     else if (align & Qt::AlignBottom)
       
  1564         yo = qMax(cr.height()-rh, qreal(0));
       
  1565     return QRectF(cr.x(), yo + cr.y(), cr.width(), cr.height());
       
  1566 }
       
  1567 
       
  1568 // Returns the point in the document rect adjusted with p
       
  1569 QPoint QLabelPrivate::layoutPoint(const QPoint& p) const
       
  1570 {
       
  1571     QRect lr = layoutRect().toRect();
       
  1572     return p - lr.topLeft();
       
  1573 }
       
  1574 
       
  1575 #ifndef QT_NO_CONTEXTMENU
       
  1576 QMenu *QLabelPrivate::createStandardContextMenu(const QPoint &pos)
       
  1577 {
       
  1578     QString linkToCopy;
       
  1579     QPoint p;
       
  1580     if (control && isRichText) {
       
  1581         p = layoutPoint(pos);
       
  1582         linkToCopy = control->document()->documentLayout()->anchorAt(p);
       
  1583     }
       
  1584 
       
  1585     if (linkToCopy.isEmpty() && !control)
       
  1586         return 0;
       
  1587 
       
  1588     return control->createStandardContextMenu(p, q_func());
       
  1589 }
       
  1590 #endif
       
  1591 
       
  1592 /*!
       
  1593     \fn void QLabel::linkHovered(const QString &link)
       
  1594     \since 4.2
       
  1595 
       
  1596     This signal is emitted when the user hovers over a link. The URL
       
  1597     referred to by the anchor is passed in \a link.
       
  1598 
       
  1599     \sa linkActivated()
       
  1600 */
       
  1601 
       
  1602 
       
  1603 /*!
       
  1604     \fn void QLabel::linkActivated(const QString &link)
       
  1605     \since 4.2
       
  1606 
       
  1607     This signal is emitted when the user clicks a link. The URL
       
  1608     referred to by the anchor is passed in \a link.
       
  1609 
       
  1610     \sa linkHovered()
       
  1611 */
       
  1612 
       
  1613 QT_END_NAMESPACE
       
  1614 
       
  1615 #include "moc_qlabel.cpp"