src/gui/widgets/qlabel.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/widgets/qlabel.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,1615 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpainter.h"
+#include "qevent.h"
+#include "qdrawutil.h"
+#include "qapplication.h"
+#include "qabstractbutton.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include <limits.h>
+#include "qaction.h"
+#include "qclipboard.h"
+#include <qdebug.h>
+#include <qurl.h>
+#include "qlabel_p.h"
+#include "private/qstylesheetstyle_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+    \class QLabel
+    \brief The QLabel widget provides a text or image display.
+
+    \ingroup basicwidgets
+
+    QLabel is used for displaying text or an image. No user
+    interaction functionality is provided. The visual appearance of
+    the label can be configured in various ways, and it can be used
+    for specifying a focus mnemonic key for another widget.
+
+    A QLabel can contain any of the following content types:
+
+    \table
+    \header \o Content \o Setting
+    \row \o Plain text
+         \o Pass a QString to setText().
+    \row \o Rich text
+         \o Pass a QString that contains rich text to setText().
+    \row \o A pixmap
+         \o Pass a QPixmap to setPixmap().
+    \row \o A movie
+         \o Pass a QMovie to setMovie().
+    \row \o A number
+         \o Pass an \e int or a \e double to setNum(), which converts
+            the number to plain text.
+    \row \o Nothing
+         \o The same as an empty plain text. This is the default. Set
+            by clear().
+    \endtable
+
+    When the content is changed using any of these functions, any
+    previous content is cleared.
+
+    By default, labels display \l{alignment}{left-aligned, vertically-centered}
+    text and images, where any tabs in the text to be displayed are
+    \l{Qt::TextExpandTabs}{automatically expanded}. However, the look
+    of a QLabel can be adjusted and fine-tuned in several ways.
+
+    The positioning of the content within the QLabel widget area can
+    be tuned with setAlignment() and setIndent(). Text content can
+    also wrap lines along word boundaries with setWordWrap(). For
+    example, this code sets up a sunken panel with a two-line text in
+    the bottom right corner (both lines being flush with the right
+    side of the label):
+
+    \snippet doc/src/snippets/code/src_gui_widgets_qlabel.cpp 0
+
+    The properties and functions QLabel inherits from QFrame can also
+    be used to specify the widget frame to be used for any given label.
+
+    A QLabel is often used as a label for an interactive widget. For
+    this use QLabel provides a useful mechanism for adding an
+    mnemonic (see QKeySequence) that will set the keyboard focus to
+    the other widget (called the QLabel's "buddy"). For example:
+
+    \snippet doc/src/snippets/code/src_gui_widgets_qlabel.cpp 1
+
+    In this example, keyboard focus is transferred to the label's
+    buddy (the QLineEdit) when the user presses Alt+P. If the buddy
+    was a button (inheriting from QAbstractButton), triggering the
+    mnemonic would emulate a button click.
+
+    \table 100%
+    \row
+    \o \inlineimage macintosh-label.png Screenshot of a Macintosh style label
+    \o A label shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
+    \row
+    \o \inlineimage plastique-label.png Screenshot of a Plastique style label
+    \o A label shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
+    \row
+    \o \inlineimage windowsxp-label.png Screenshot of a Windows XP style label
+    \o A label shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
+    \endtable
+
+    \sa QLineEdit, QTextEdit, QPixmap, QMovie,
+        {fowler}{GUI Design Handbook: Label}
+*/
+
+#ifndef QT_NO_PICTURE
+/*!
+    Returns the label's picture or 0 if the label doesn't have a
+    picture.
+*/
+
+const QPicture *QLabel::picture() const
+{
+    Q_D(const QLabel);
+    return d->picture;
+}
+#endif
+
+
+/*!
+    Constructs an empty label.
+
+    The \a parent and widget flag \a f, arguments are passed
+    to the QFrame constructor.
+
+    \sa setAlignment(), setFrameStyle(), setIndent()
+*/
+QLabel::QLabel(QWidget *parent, Qt::WindowFlags f)
+    : QFrame(*new QLabelPrivate(), parent, f)
+{
+    Q_D(QLabel);
+    d->init();
+}
+
+/*!
+    Constructs a label that displays the text, \a text.
+
+    The \a parent and widget flag \a f, arguments are passed
+    to the QFrame constructor.
+
+    \sa setText(), setAlignment(), setFrameStyle(), setIndent()
+*/
+QLabel::QLabel(const QString &text, QWidget *parent, Qt::WindowFlags f)
+        : QFrame(*new QLabelPrivate(), parent, f)
+{
+    Q_D(QLabel);
+    d->init();
+    setText(text);
+}
+
+
+#ifdef QT3_SUPPORT
+/*! \obsolete
+    Constructs an empty label.
+
+    The \a parent, \a name and widget flag \a f, arguments are passed
+    to the QFrame constructor.
+
+    \sa setAlignment(), setFrameStyle(), setIndent()
+*/
+
+QLabel::QLabel(QWidget *parent, const char *name, Qt::WindowFlags f)
+    : QFrame(*new QLabelPrivate(), parent, f)
+{
+    Q_D(QLabel);
+    if (name)
+        setObjectName(QString::fromAscii(name));
+    d->init();
+}
+
+
+/*! \obsolete
+    Constructs a label that displays the text, \a text.
+
+    The \a parent, \a name and widget flag \a f, arguments are passed
+    to the QFrame constructor.
+
+    \sa setText(), setAlignment(), setFrameStyle(), setIndent()
+*/
+
+QLabel::QLabel(const QString &text, QWidget *parent, const char *name,
+                Qt::WindowFlags f)
+        : QFrame(*new QLabelPrivate(), parent, f)
+{
+    Q_D(QLabel);
+    if (name)
+        setObjectName(QString::fromAscii(name));
+    d->init();
+    setText(text);
+}
+
+
+/*! \obsolete
+    Constructs a label that displays the text \a text. The label has a
+    buddy widget, \a buddy.
+
+    If the \a text contains an underlined letter (a letter preceded by
+    an ampersand, \&), when the user presses Alt+ the underlined letter,
+    focus is passed to the buddy widget.
+
+    The \a parent, \a name and widget flag, \a f, arguments are passed
+    to the QFrame constructor.
+
+    \sa setText(), setBuddy(), setAlignment(), setFrameStyle(),
+    setIndent()
+*/
+QLabel::QLabel(QWidget *buddy, const QString &text,
+                QWidget *parent, const char *name, Qt::WindowFlags f)
+    : QFrame(*new QLabelPrivate(), parent, f)
+{
+    Q_D(QLabel);
+    if (name)
+        setObjectName(QString::fromAscii(name));
+    d->init();
+#ifndef QT_NO_SHORTCUT
+    setBuddy(buddy);
+#endif
+    setText(text);
+}
+#endif //QT3_SUPPORT
+
+/*!
+    Destroys the label.
+*/
+
+QLabel::~QLabel()
+{
+    Q_D(QLabel);
+    d->clearContents();
+}
+
+void QLabelPrivate::init()
+{
+    Q_Q(QLabel);
+
+    valid_hints = false;
+    margin = 0;
+#ifndef QT_NO_MOVIE
+    movie = 0;
+#endif
+#ifndef QT_NO_SHORTCUT
+    shortcutId = 0;
+#endif
+    pixmap = 0;
+    scaledpixmap = 0;
+    cachedimage = 0;
+#ifndef QT_NO_PICTURE
+    picture = 0;
+#endif
+    align = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextExpandTabs;
+    indent = -1;
+    scaledcontents = false;
+    textLayoutDirty = false;
+    textDirty = false;
+    textformat = Qt::AutoText;
+    control = 0;
+    textInteractionFlags = Qt::LinksAccessibleByMouse;
+    isRichText = false;
+    isTextLabel = false;
+
+    q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred,
+                                 QSizePolicy::Label));
+
+#ifndef QT_NO_CURSOR
+    validCursor = false;
+    onAnchor = false;
+#endif
+
+    openExternalLinks = false;
+
+    setLayoutItemMargins(QStyle::SE_LabelLayoutItem);
+}
+
+
+/*!
+    \property QLabel::text
+    \brief the label's text
+
+    If no text has been set this will return an empty string. Setting
+    the text clears any previous content.
+
+    The text will be interpreted either as plain text or as rich
+    text, depending on the text format setting; see setTextFormat().
+    The default setting is Qt::AutoText; i.e. QLabel will try to
+    auto-detect the format of the text set.
+
+    If a buddy has been set, the buddy mnemonic key is updated
+    from the new text.
+
+    Note that QLabel is well-suited to display small rich text
+    documents, such as small documents that get their document
+    specific settings (font, text color, link color) from the label's
+    palette and font properties. For large documents, use QTextEdit
+    in read-only mode instead. QTextEdit can also provide a scroll bar
+    when necessary.
+
+    \note This function enables mouse tracking if \a text contains rich
+    text.
+
+    \sa setTextFormat(), setBuddy(), alignment
+*/
+
+void QLabel::setText(const QString &text)
+{
+    Q_D(QLabel);
+    if (d->text == text)
+        return;
+
+    QTextControl *oldControl = d->control;
+    d->control = 0;
+
+    d->clearContents();
+    d->text = text;
+    d->isTextLabel = true;
+    d->textDirty = true;
+    d->isRichText = d->textformat == Qt::RichText
+                    || (d->textformat == Qt::AutoText && Qt::mightBeRichText(d->text));
+
+    d->control = oldControl;
+
+    if (d->needTextControl()) {
+        d->ensureTextControl();
+    } else {
+        delete d->control;
+        d->control = 0;
+    }
+
+    if (d->isRichText) {
+        setMouseTracking(true);
+    } else {
+        // Note: mouse tracking not disabled intentionally
+    }
+
+#ifndef QT_NO_SHORTCUT
+    if (d->buddy)
+        d->updateShortcut();
+#endif
+
+    d->updateLabel();
+}
+
+QString QLabel::text() const
+{
+    Q_D(const QLabel);
+    return d->text;
+}
+
+/*!
+    Clears any label contents.
+*/
+
+void QLabel::clear()
+{
+    Q_D(QLabel);
+    d->clearContents();
+    d->updateLabel();
+}
+
+/*!
+    \property QLabel::pixmap
+    \brief the label's pixmap
+
+    If no pixmap has been set this will return 0.
+
+    Setting the pixmap clears any previous content. The buddy
+    shortcut, if any, is disabled.
+*/
+void QLabel::setPixmap(const QPixmap &pixmap)
+{
+    Q_D(QLabel);
+    if (!d->pixmap || d->pixmap->cacheKey() != pixmap.cacheKey()) {
+        d->clearContents();
+        d->pixmap = new QPixmap(pixmap);
+    }
+
+    if (d->pixmap->depth() == 1 && !d->pixmap->mask())
+        d->pixmap->setMask(*((QBitmap *)d->pixmap));
+
+    d->updateLabel();
+}
+
+const QPixmap *QLabel::pixmap() const
+{
+    Q_D(const QLabel);
+    return d->pixmap;
+}
+
+#ifndef QT_NO_PICTURE
+/*!
+    Sets the label contents to \a picture. Any previous content is
+    cleared.
+
+    The buddy shortcut, if any, is disabled.
+
+    \sa picture(), setBuddy()
+*/
+
+void QLabel::setPicture(const QPicture &picture)
+{
+    Q_D(QLabel);
+    d->clearContents();
+    d->picture = new QPicture(picture);
+
+    d->updateLabel();
+}
+#endif // QT_NO_PICTURE
+
+/*!
+    Sets the label contents to plain text containing the textual
+    representation of integer \a num. Any previous content is cleared.
+    Does nothing if the integer's string representation is the same as
+    the current contents of the label.
+
+    The buddy shortcut, if any, is disabled.
+
+    \sa setText(), QString::setNum(), setBuddy()
+*/
+
+void QLabel::setNum(int num)
+{
+    QString str;
+    str.setNum(num);
+    setText(str);
+}
+
+/*!
+    \overload
+
+    Sets the label contents to plain text containing the textual
+    representation of double \a num. Any previous content is cleared.
+    Does nothing if the double's string representation is the same as
+    the current contents of the label.
+
+    The buddy shortcut, if any, is disabled.
+
+    \sa setText(), QString::setNum(), setBuddy()
+*/
+
+void QLabel::setNum(double num)
+{
+    QString str;
+    str.setNum(num);
+    setText(str);
+}
+
+/*!
+    \property QLabel::alignment
+    \brief the alignment of the label's contents
+
+    By default, the contents of the label are left-aligned and vertically-centered.
+
+    \sa text
+*/
+
+void QLabel::setAlignment(Qt::Alignment alignment)
+{
+    Q_D(QLabel);
+    if (alignment == (d->align & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask)))
+        return;
+    d->align = (d->align & ~(Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask))
+               | (alignment & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask));
+
+    d->updateLabel();
+}
+
+#ifdef QT3_SUPPORT
+/*!
+    Use setAlignment(Qt::Alignment) instead.
+
+    If \a alignment specifies text flags as well, use setTextFormat()
+    to set those.
+*/
+void QLabel::setAlignment(int alignment)
+{
+    Q_D(QLabel);
+    d->align = alignment & ~(Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask|Qt::TextWordWrap);
+    setAlignment(Qt::Alignment(QFlag(alignment)));
+}
+#endif
+
+Qt::Alignment QLabel::alignment() const
+{
+    Q_D(const QLabel);
+    return QFlag(d->align & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask));
+}
+
+
+/*!
+    \property QLabel::wordWrap
+    \brief the label's word-wrapping policy
+
+    If this property is true then label text is wrapped where
+    necessary at word-breaks; otherwise it is not wrapped at all.
+
+    By default, word wrap is disabled.
+
+    \sa text
+*/
+void QLabel::setWordWrap(bool on)
+{
+    Q_D(QLabel);
+    if (on)
+        d->align |= Qt::TextWordWrap;
+    else
+        d->align &= ~Qt::TextWordWrap;
+
+    d->updateLabel();
+}
+
+bool QLabel::wordWrap() const
+{
+    Q_D(const QLabel);
+    return d->align & Qt::TextWordWrap;
+}
+
+/*!
+    \property QLabel::indent
+    \brief the label's text indent in pixels
+
+    If a label displays text, the indent applies to the left edge if
+    alignment() is Qt::AlignLeft, to the right edge if alignment() is
+    Qt::AlignRight, to the top edge if alignment() is Qt::AlignTop, and
+    to to the bottom edge if alignment() is Qt::AlignBottom.
+
+    If indent is negative, or if no indent has been set, the label
+    computes the effective indent as follows: If frameWidth() is 0,
+    the effective indent becomes 0. If frameWidth() is greater than 0,
+    the effective indent becomes half the width of the "x" character
+    of the widget's current font().
+
+    By default, the indent is -1, meaning that an effective indent is
+    calculating in the manner described above.
+
+    \sa alignment, margin, frameWidth(), font()
+*/
+
+void QLabel::setIndent(int indent)
+{
+    Q_D(QLabel);
+    d->indent = indent;
+    d->updateLabel();
+}
+
+int QLabel::indent() const
+{
+    Q_D(const QLabel);
+    return d->indent;
+}
+
+
+/*!
+    \property QLabel::margin
+    \brief the width of the margin
+
+    The margin is the distance between the innermost pixel of the
+    frame and the outermost pixel of contents.
+
+    The default margin is 0.
+
+    \sa indent
+*/
+int QLabel::margin() const
+{
+    Q_D(const QLabel);
+    return d->margin;
+}
+
+void QLabel::setMargin(int margin)
+{
+    Q_D(QLabel);
+    if (d->margin == margin)
+        return;
+    d->margin = margin;
+    d->updateLabel();
+}
+
+/*!
+    Returns the size that will be used if the width of the label is \a
+    w. If \a w is -1, the sizeHint() is returned. If \a w is 0 minimumSizeHint() is returned
+*/
+QSize QLabelPrivate::sizeForWidth(int w) const
+{
+    Q_Q(const QLabel);
+    if(q->minimumWidth() > 0)
+        w = qMax(w, q->minimumWidth());
+    QSize contentsMargin(leftmargin + rightmargin, topmargin + bottommargin);
+
+    QRect br;
+
+    int hextra = 2 * margin;
+    int vextra = hextra;
+    QFontMetrics fm = q->fontMetrics();
+
+    if (pixmap && !pixmap->isNull())
+        br = pixmap->rect();
+#ifndef QT_NO_PICTURE
+    else if (picture && !picture->isNull())
+        br = picture->boundingRect();
+#endif
+#ifndef QT_NO_MOVIE
+    else if (movie && !movie->currentPixmap().isNull())
+        br = movie->currentPixmap().rect();
+#endif
+    else if (isTextLabel) {
+        int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align));
+        // Add indentation
+        int m = indent;
+
+        if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
+            m = fm.width(QLatin1Char('x')) - margin*2;
+        if (m > 0) {
+            if ((align & Qt::AlignLeft) || (align & Qt::AlignRight))
+                hextra += m;
+            if ((align & Qt::AlignTop) || (align & Qt::AlignBottom))
+                vextra += m;
+        }
+
+        if (control) {
+            ensureTextLayouted();
+            const qreal oldTextWidth = control->textWidth();
+            // Calculate the length of document if w is the width
+            if (align & Qt::TextWordWrap) {
+                if (w >= 0) {
+                    w = qMax(w-hextra-contentsMargin.width(), 0); // strip margin and indent
+                    control->setTextWidth(w);
+                } else {
+                    control->adjustSize();
+                }
+            } else {
+                control->setTextWidth(-1);
+            }
+            br = QRect(QPoint(0, 0), control->size().toSize());
+
+            // restore state
+            control->setTextWidth(oldTextWidth);
+        } else {
+            // Turn off center alignment in order to avoid rounding errors for centering,
+            // since centering involves a division by 2. At the end, all we want is the size.
+            int flags = align & ~(Qt::AlignVCenter | Qt::AlignHCenter);
+            if (hasShortcut) {
+                flags |= Qt::TextShowMnemonic;
+                QStyleOption opt;
+                opt.initFrom(q);
+                if (!q->style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, q))
+                    flags |= Qt::TextHideMnemonic;
+            }
+
+            bool tryWidth = (w < 0) && (align & Qt::TextWordWrap);
+            if (tryWidth)
+                w = fm.averageCharWidth() * 80;
+            else if (w < 0)
+                w = 2000;
+            w -= (hextra + contentsMargin.width());
+            br = fm.boundingRect(0, 0, w ,2000, flags, text);
+            if (tryWidth && br.height() < 4*fm.lineSpacing() && br.width() > w/2)
+                br = fm.boundingRect(0, 0, w/2, 2000, flags, text);
+            if (tryWidth && br.height() < 2*fm.lineSpacing() && br.width() > w/4)
+                br = fm.boundingRect(0, 0, w/4, 2000, flags, text);
+        }
+    } else {
+        br = QRect(QPoint(0, 0), QSize(fm.averageCharWidth(), fm.lineSpacing()));
+    }
+
+    const QSize contentsSize(br.width() + hextra, br.height() + vextra);
+    return (contentsSize + contentsMargin).expandedTo(q->minimumSize());
+}
+
+
+/*!
+  \reimp
+*/
+
+int QLabel::heightForWidth(int w) const
+{
+    Q_D(const QLabel);
+    if (d->isTextLabel)
+        return d->sizeForWidth(w).height();
+    return QWidget::heightForWidth(w);
+}
+
+/*!
+    \property QLabel::openExternalLinks
+    \since 4.2
+
+    Specifies whether QLabel should automatically open links using
+    QDesktopServices::openUrl() instead of emitting the
+    linkActivated() signal.
+
+    \bold{Note:} The textInteractionFlags set on the label need to include
+    either LinksAccessibleByMouse or LinksAccessibleByKeyboard.
+
+    The default value is false.
+
+    \sa textInteractionFlags()
+*/
+bool QLabel::openExternalLinks() const
+{
+    Q_D(const QLabel);
+    return d->openExternalLinks;
+}
+
+void QLabel::setOpenExternalLinks(bool open)
+{
+    Q_D(QLabel);
+    d->openExternalLinks = open;
+    if (d->control)
+        d->control->setOpenExternalLinks(open);
+}
+
+/*!
+    \property QLabel::textInteractionFlags
+    \since 4.2
+
+    Specifies how the label should interact with user input if it displays text.
+
+    If the flags contain Qt::LinksAccessibleByKeyboard the focus policy is also
+    automatically set to Qt::StrongFocus. If Qt::TextSelectableByKeyboard is set
+    then the focus policy is set to Qt::ClickFocus.
+
+    The default value is Qt::LinksAccessibleByMouse.
+*/
+void QLabel::setTextInteractionFlags(Qt::TextInteractionFlags flags)
+{
+    Q_D(QLabel);
+    if (d->textInteractionFlags == flags)
+        return;
+    d->textInteractionFlags = flags;
+    if (flags & Qt::LinksAccessibleByKeyboard)
+        setFocusPolicy(Qt::StrongFocus);
+    else if (flags & (Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse))
+        setFocusPolicy(Qt::ClickFocus);
+    else
+        setFocusPolicy(Qt::NoFocus);
+
+    if (d->needTextControl()) {
+        d->ensureTextControl();
+    } else {
+        delete d->control;
+        d->control = 0;
+    }
+
+    if (d->control)
+        d->control->setTextInteractionFlags(d->textInteractionFlags);
+}
+
+Qt::TextInteractionFlags QLabel::textInteractionFlags() const
+{
+    Q_D(const QLabel);
+    return d->textInteractionFlags;
+}
+
+/*!\reimp
+*/
+QSize QLabel::sizeHint() const
+{
+    Q_D(const QLabel);
+    if (!d->valid_hints)
+        (void) QLabel::minimumSizeHint();
+    return d->sh;
+}
+
+/*!
+  \reimp
+*/
+QSize QLabel::minimumSizeHint() const
+{
+    Q_D(const QLabel);
+    if (d->valid_hints) {
+        if (d->sizePolicy == sizePolicy())
+            return d->msh;
+    }
+
+    ensurePolished();
+    d->valid_hints = true;
+    d->sh = d->sizeForWidth(-1); // wrap ? golden ratio : min doc size
+    QSize msh(-1, -1);
+
+    if (!d->isTextLabel) {
+        msh = d->sh;
+    } else {
+        msh.rheight() = d->sizeForWidth(QWIDGETSIZE_MAX).height(); // height for one line
+        msh.rwidth() = d->sizeForWidth(0).width(); // wrap ? size of biggest word : min doc size
+        if (d->sh.height() < msh.height())
+            msh.rheight() = d->sh.height();
+    }
+    d->msh = msh;
+    d->sizePolicy = sizePolicy();
+    return msh;
+}
+
+/*!\reimp
+*/
+void QLabel::mousePressEvent(QMouseEvent *ev)
+{
+    Q_D(QLabel);
+    d->sendControlEvent(ev);
+}
+
+/*!\reimp
+*/
+void QLabel::mouseMoveEvent(QMouseEvent *ev)
+{
+    Q_D(QLabel);
+    d->sendControlEvent(ev);
+}
+
+/*!\reimp
+*/
+void QLabel::mouseReleaseEvent(QMouseEvent *ev)
+{
+    Q_D(QLabel);
+    d->sendControlEvent(ev);
+}
+
+/*!\reimp
+*/
+void QLabel::contextMenuEvent(QContextMenuEvent *ev)
+{
+#ifdef QT_NO_CONTEXTMENU
+    Q_UNUSED(ev);
+#else
+    Q_D(QLabel);
+    if (!d->isTextLabel) {
+        ev->ignore();
+        return;
+    }
+    QMenu *menu = d->createStandardContextMenu(ev->pos());
+    if (!menu) {
+        ev->ignore();
+        return;
+    }
+    ev->accept();
+    menu->exec(ev->globalPos());
+    delete menu;
+#endif
+}
+
+/*!
+    \reimp
+*/
+void QLabel::focusInEvent(QFocusEvent *ev)
+{
+    Q_D(QLabel);
+    if (d->isTextLabel) {
+        d->ensureTextControl();
+        d->sendControlEvent(ev);
+    }
+    QFrame::focusInEvent(ev);
+}
+
+/*!
+    \reimp
+*/
+void QLabel::focusOutEvent(QFocusEvent *ev)
+{
+    Q_D(QLabel);
+    if (d->control) {
+        d->sendControlEvent(ev);
+        QTextCursor cursor = d->control->textCursor();
+        Qt::FocusReason reason = ev->reason();
+        if (reason != Qt::ActiveWindowFocusReason
+            && reason != Qt::PopupFocusReason
+            && cursor.hasSelection()) {
+            cursor.clearSelection();
+            d->control->setTextCursor(cursor);
+        }
+    }
+
+    QFrame::focusOutEvent(ev);
+}
+
+/*!\reimp
+*/
+bool QLabel::focusNextPrevChild(bool next)
+{
+    Q_D(QLabel);
+    if (d->control && d->control->setFocusToNextOrPreviousAnchor(next))
+        return true;
+    return QFrame::focusNextPrevChild(next);
+}
+
+/*!\reimp
+*/
+void QLabel::keyPressEvent(QKeyEvent *ev)
+{
+    Q_D(QLabel);
+    d->sendControlEvent(ev);
+}
+
+/*!\reimp
+*/
+bool QLabel::event(QEvent *e)
+{
+    Q_D(QLabel);
+    QEvent::Type type = e->type();
+
+#ifndef QT_NO_SHORTCUT
+    if (type == QEvent::Shortcut) {
+        QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
+        if (se->shortcutId() == d->shortcutId) {
+            QWidget * w = d->buddy;
+            QAbstractButton *button = qobject_cast<QAbstractButton *>(w);
+            if (w->focusPolicy() != Qt::NoFocus)
+                w->setFocus(Qt::ShortcutFocusReason);
+            if (button && !se->isAmbiguous())
+                button->animateClick();
+            else
+                window()->setAttribute(Qt::WA_KeyboardFocusChange);
+            return true;
+        }
+    } else
+#endif
+    if (type == QEvent::Resize) {
+        if (d->control)
+            d->textLayoutDirty = true;
+    } else if (e->type() == QEvent::StyleChange
+#ifdef Q_WS_MAC
+               || e->type() == QEvent::MacSizeChange
+#endif
+               ) {
+        d->setLayoutItemMargins(QStyle::SE_LabelLayoutItem);
+        d->updateLabel();
+    }
+
+    return QFrame::event(e);
+}
+
+/*!\reimp
+*/
+void QLabel::paintEvent(QPaintEvent *)
+{
+    Q_D(QLabel);
+    QStyle *style = QWidget::style();
+    QPainter painter(this);
+    drawFrame(&painter);
+    QRect cr = contentsRect();
+    cr.adjust(d->margin, d->margin, -d->margin, -d->margin);
+    int align = QStyle::visualAlignment(layoutDirection(), QFlag(d->align));
+
+#ifndef QT_NO_MOVIE
+    if (d->movie) {
+        if (d->scaledcontents)
+            style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap().scaled(cr.size()));
+        else
+            style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap());
+    }
+    else
+#endif
+    if (d->isTextLabel) {
+        QRectF lr = d->layoutRect();
+        QStyleOption opt;
+        opt.initFrom(this);
+#ifndef QT_NO_STYLE_STYLESHEET
+        if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) {
+            cssStyle->styleSheetPalette(this, &opt, &opt.palette);
+        }
+#endif
+        if (d->control) {
+#ifndef QT_NO_SHORTCUT
+            const bool underline = (bool)style->styleHint(QStyle::SH_UnderlineShortcut, 0, this, 0);
+            if (d->shortcutId != 0
+                && underline != d->shortcutCursor.charFormat().fontUnderline()) {
+                QTextCharFormat fmt;
+                fmt.setFontUnderline(underline);
+                d->shortcutCursor.mergeCharFormat(fmt);
+            }
+#endif
+            d->ensureTextLayouted();
+
+            QAbstractTextDocumentLayout::PaintContext context;
+            if (!isEnabled() && !d->control &&
+                // We cannot support etched for rich text controls because custom
+                // colors and links will override the light palette
+                style->styleHint(QStyle::SH_EtchDisabledText, &opt, this)) {
+                context.palette = opt.palette;
+                context.palette.setColor(QPalette::Text, context.palette.light().color());
+                painter.save();
+                painter.translate(lr.x() + 1, lr.y() + 1);
+                painter.setClipRect(lr.translated(-lr.x() - 1, -lr.y() - 1));
+                QAbstractTextDocumentLayout *layout = d->control->document()->documentLayout();
+                layout->draw(&painter, context);
+                painter.restore();
+            }
+
+            // Adjust the palette
+            context.palette = opt.palette;
+
+            if (foregroundRole() != QPalette::Text && isEnabled())
+                context.palette.setColor(QPalette::Text, context.palette.color(foregroundRole()));
+
+            painter.save();
+            painter.translate(lr.topLeft());
+            painter.setClipRect(lr.translated(-lr.x(), -lr.y()));
+            d->control->setPalette(context.palette);
+            d->control->drawContents(&painter, QRectF(), this);
+            painter.restore();
+        } else {
+            int flags = align;
+            if (d->hasShortcut) {
+                flags |= Qt::TextShowMnemonic;
+                if (!style->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
+                    flags |= Qt::TextHideMnemonic;
+            }
+            style->drawItemText(&painter, lr.toRect(), flags, opt.palette, isEnabled(), d->text, foregroundRole());
+        }
+    } else
+#ifndef QT_NO_PICTURE
+    if (d->picture) {
+        QRect br = d->picture->boundingRect();
+        int rw = br.width();
+        int rh = br.height();
+        if (d->scaledcontents) {
+            painter.save();
+            painter.translate(cr.x(), cr.y());
+            painter.scale((double)cr.width()/rw, (double)cr.height()/rh);
+            painter.drawPicture(-br.x(), -br.y(), *d->picture);
+            painter.restore();
+        } else {
+            int xo = 0;
+            int yo = 0;
+            if (align & Qt::AlignVCenter)
+                yo = (cr.height()-rh)/2;
+            else if (align & Qt::AlignBottom)
+                yo = cr.height()-rh;
+            if (align & Qt::AlignRight)
+                xo = cr.width()-rw;
+            else if (align & Qt::AlignHCenter)
+                xo = (cr.width()-rw)/2;
+            painter.drawPicture(cr.x()+xo-br.x(), cr.y()+yo-br.y(), *d->picture);
+        }
+    } else
+#endif
+    if (d->pixmap && !d->pixmap->isNull()) {
+        QPixmap pix;
+        if (d->scaledcontents) {
+            if (!d->scaledpixmap || d->scaledpixmap->size() != cr.size()) {
+                if (!d->cachedimage)
+                    d->cachedimage = new QImage(d->pixmap->toImage());
+                delete d->scaledpixmap;
+                d->scaledpixmap = new QPixmap(QPixmap::fromImage(d->cachedimage->scaled(cr.size(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)));
+            }
+            pix = *d->scaledpixmap;
+        } else
+            pix = *d->pixmap;
+        QStyleOption opt;
+        opt.initFrom(this);
+        if (!isEnabled())
+            pix = style->generatedIconPixmap(QIcon::Disabled, pix, &opt);
+        style->drawItemPixmap(&painter, cr, align, pix);
+    }
+}
+
+
+/*!
+    Updates the label, but not the frame.
+*/
+
+void QLabelPrivate::updateLabel()
+{
+    Q_Q(QLabel);
+    valid_hints = false;
+
+    if (isTextLabel) {
+        QSizePolicy policy = q->sizePolicy();
+        const bool wrap = align & Qt::TextWordWrap;
+        policy.setHeightForWidth(wrap);
+        if (policy != q->sizePolicy())  // ### should be replaced by WA_WState_OwnSizePolicy idiom
+            q->setSizePolicy(policy);
+        textLayoutDirty = true;
+    }
+    q->updateGeometry();
+    q->update(q->contentsRect());
+}
+
+#ifndef QT_NO_SHORTCUT
+/*!
+    Sets this label's buddy to \a buddy.
+
+    When the user presses the shortcut key indicated by this label,
+    the keyboard focus is transferred to the label's buddy widget.
+
+    The buddy mechanism is only available for QLabels that contain
+    text in which one character is prefixed with an ampersand, '&'.
+    This character is set as the shortcut key. See the \l
+    QKeySequence::mnemonic() documentation for details (to display an
+    actual ampersand, use '&&').
+
+    In a dialog, you might create two data entry widgets and a label
+    for each, and set up the geometry layout so each label is just to
+    the left of its data entry widget (its "buddy"), for example:
+    \snippet doc/src/snippets/code/src_gui_widgets_qlabel.cpp 2
+
+    With the code above, the focus jumps to the Name field when the
+    user presses Alt+N, and to the Phone field when the user presses
+    Alt+P.
+
+    To unset a previously set buddy, call this function with \a buddy
+    set to 0.
+
+    \sa buddy(), setText(), QShortcut, setAlignment()
+*/
+
+void QLabel::setBuddy(QWidget *buddy)
+{
+    Q_D(QLabel);
+    d->buddy = buddy;
+    if (d->isTextLabel) {
+        if (d->shortcutId)
+            releaseShortcut(d->shortcutId);
+        d->shortcutId = 0;
+        d->textDirty = true;
+        if (buddy)
+            d->updateShortcut(); // grab new shortcut
+        d->updateLabel();
+    }
+}
+
+
+/*!
+    Returns this label's buddy, or 0 if no buddy is currently set.
+
+    \sa setBuddy()
+*/
+
+QWidget * QLabel::buddy() const
+{
+    Q_D(const QLabel);
+    return d->buddy;
+}
+
+void QLabelPrivate::updateShortcut()
+{
+    Q_Q(QLabel);
+    Q_ASSERT(shortcutId == 0);
+    // Introduce an extra boolean to indicate the presence of a shortcut in the
+    // text. We cannot use the shortcutId itself because on the mac mnemonics are
+    // off by default, so QKeySequence::mnemonic always returns an empty sequence.
+    // But then we do want to hide the ampersands, so we can't use shortcutId.
+    hasShortcut = false;
+
+    if (control) {
+        ensureTextPopulated();
+        // Underline the first character that follows an ampersand
+        shortcutCursor = control->document()->find(QLatin1String("&"));
+        if (shortcutCursor.isNull())
+            return;
+        hasShortcut = true;
+        shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
+        shortcutCursor.deleteChar(); // remove the ampersand
+        shortcutCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+    } else {
+        if (!text.contains(QLatin1Char('&')))
+            return;
+        hasShortcut = true;
+        shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
+    }
+}
+
+#endif // QT_NO_SHORTCUT
+
+#ifndef QT_NO_MOVIE
+void QLabelPrivate::_q_movieUpdated(const QRect& rect)
+{
+    Q_Q(QLabel);
+    if (movie && movie->isValid()) {
+        QRect r;
+        if (scaledcontents) {
+            QRect cr = q->contentsRect();
+            QRect pixmapRect(cr.topLeft(), movie->currentPixmap().size());
+            if (pixmapRect.isEmpty())
+                return;
+            r.setRect(cr.left(), cr.top(),
+                      (rect.width() * cr.width()) / pixmapRect.width(),
+                      (rect.height() * cr.height()) / pixmapRect.height());
+        } else {
+            r = q->style()->itemPixmapRect(q->contentsRect(), align, movie->currentPixmap());
+            r.translate(rect.x(), rect.y());
+            r.setWidth(qMin(r.width(), rect.width()));
+            r.setHeight(qMin(r.height(), rect.height()));
+        }
+        q->update(r);
+    }
+}
+
+void QLabelPrivate::_q_movieResized(const QSize& size)
+{
+    Q_Q(QLabel);
+    q->update(); //we need to refresh the whole background in case the new size is smaler
+    valid_hints = false;
+    _q_movieUpdated(QRect(QPoint(0,0), size));
+    q->updateGeometry();
+}
+
+/*!
+    Sets the label contents to \a movie. Any previous content is
+    cleared. The label does NOT take ownership of the movie.
+
+    The buddy shortcut, if any, is disabled.
+
+    \sa movie(), setBuddy()
+*/
+
+void QLabel::setMovie(QMovie *movie)
+{
+    Q_D(QLabel);
+    d->clearContents();
+
+    if (!movie)
+        return;
+
+    d->movie = movie;
+    connect(movie, SIGNAL(resized(QSize)), this, SLOT(_q_movieResized(QSize)));
+    connect(movie, SIGNAL(updated(QRect)), this, SLOT(_q_movieUpdated(QRect)));
+
+    // Assume that if the movie is running,
+    // resize/update signals will come soon enough
+    if (movie->state() != QMovie::Running)
+        d->updateLabel();
+}
+
+#endif // QT_NO_MOVIE
+
+/*!
+  \internal
+
+  Clears any contents, without updating/repainting the label.
+*/
+
+void QLabelPrivate::clearContents()
+{
+    delete control;
+    control = 0;
+    isTextLabel = false;
+    hasShortcut = false;
+
+#ifndef QT_NO_PICTURE
+    delete picture;
+    picture = 0;
+#endif
+    delete scaledpixmap;
+    scaledpixmap = 0;
+    delete cachedimage;
+    cachedimage = 0;
+    delete pixmap;
+    pixmap = 0;
+
+    text.clear();
+    Q_Q(QLabel);
+#ifndef QT_NO_SHORTCUT
+    if (shortcutId)
+        q->releaseShortcut(shortcutId);
+    shortcutId = 0;
+#endif
+#ifndef QT_NO_MOVIE
+    if (movie) {
+        QObject::disconnect(movie, SIGNAL(resized(QSize)), q, SLOT(_q_movieResized(QSize)));
+        QObject::disconnect(movie, SIGNAL(updated(QRect)), q, SLOT(_q_movieUpdated(QRect)));
+    }
+    movie = 0;
+#endif
+#ifndef QT_NO_CURSOR
+    if (onAnchor) {
+        if (validCursor)
+            q->setCursor(cursor);
+        else
+            q->unsetCursor();
+    }
+    validCursor = false;
+    onAnchor = false;
+#endif
+}
+
+
+#ifndef QT_NO_MOVIE
+
+/*!
+    Returns a pointer to the label's movie, or 0 if no movie has been
+    set.
+
+    \sa setMovie()
+*/
+
+QMovie *QLabel::movie() const
+{
+    Q_D(const QLabel);
+    return d->movie;
+}
+
+#endif  // QT_NO_MOVIE
+
+/*!
+    \property QLabel::textFormat
+    \brief the label's text format
+
+    See the Qt::TextFormat enum for an explanation of the possible
+    options.
+
+    The default format is Qt::AutoText.
+
+    \sa text()
+*/
+
+Qt::TextFormat QLabel::textFormat() const
+{
+    Q_D(const QLabel);
+    return d->textformat;
+}
+
+void QLabel::setTextFormat(Qt::TextFormat format)
+{
+    Q_D(QLabel);
+    if (format != d->textformat) {
+        d->textformat = format;
+        QString t = d->text;
+        if (!t.isNull()) {
+            d->text.clear();
+            setText(t);
+        }
+    }
+}
+
+/*!
+  \reimp
+*/
+void QLabel::changeEvent(QEvent *ev)
+{
+    Q_D(QLabel);
+    if(ev->type() == QEvent::FontChange || ev->type() == QEvent::ApplicationFontChange) {
+        if (d->isTextLabel) {
+            if (d->control)
+                d->control->document()->setDefaultFont(font());
+            d->updateLabel();
+        }
+    } else if (ev->type() == QEvent::PaletteChange && d->control) {
+        d->control->setPalette(palette());
+    } else if (ev->type() == QEvent::ContentsRectChange) {
+        d->updateLabel();
+    } else if (ev->type() == QEvent::LayoutDirectionChange) {
+        if (d->isTextLabel && d->control) {
+            d->sendControlEvent(ev);
+        }
+    }
+    QFrame::changeEvent(ev);
+}
+
+/*!
+    \property QLabel::scaledContents
+    \brief whether the label will scale its contents to fill all
+    available space.
+
+    When enabled and the label shows a pixmap, it will scale the
+    pixmap to fill the available space.
+
+    This property's default is false.
+*/
+bool QLabel::hasScaledContents() const
+{
+    Q_D(const QLabel);
+    return d->scaledcontents;
+}
+
+void QLabel::setScaledContents(bool enable)
+{
+    Q_D(QLabel);
+    if ((bool)d->scaledcontents == enable)
+        return;
+    d->scaledcontents = enable;
+    if (!enable) {
+        delete d->scaledpixmap;
+        d->scaledpixmap = 0;
+        delete d->cachedimage;
+        d->cachedimage = 0;
+    }
+    update(contentsRect());
+}
+
+
+/*!
+    \fn void QLabel::setAlignment(Qt::AlignmentFlag flag)
+    \internal
+
+    Without this function, a call to e.g. setAlignment(Qt::AlignTop)
+    results in the \c QT3_SUPPORT function setAlignment(int) being called,
+    rather than setAlignment(Qt::Alignment).
+*/
+
+// Returns the rect that is available for us to draw the document
+QRect QLabelPrivate::documentRect() const
+{
+    Q_Q(const QLabel);
+    Q_ASSERT_X(isTextLabel, "documentRect", "document rect called for label that is not a text label!");
+    QRect cr = q->contentsRect();
+    cr.adjust(margin, margin, -margin, -margin);
+    const int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align));
+    int m = indent;
+    if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
+        m = q->fontMetrics().width(QLatin1Char('x')) / 2 - margin;
+    if (m > 0) {
+        if (align & Qt::AlignLeft)
+            cr.setLeft(cr.left() + m);
+        if (align & Qt::AlignRight)
+            cr.setRight(cr.right() - m);
+        if (align & Qt::AlignTop)
+            cr.setTop(cr.top() + m);
+        if (align & Qt::AlignBottom)
+            cr.setBottom(cr.bottom() - m);
+    }
+    return cr;
+}
+
+void QLabelPrivate::ensureTextPopulated() const
+{
+    if (!textDirty)
+        return;
+    if (control) {
+        QTextDocument *doc = control->document();
+        if (textDirty) {
+#ifndef QT_NO_TEXTHTMLPARSER
+            if (isRichText)
+                doc->setHtml(text);
+            else
+                doc->setPlainText(text);
+#else
+            doc->setPlainText(text);
+#endif
+            doc->setUndoRedoEnabled(false);
+        }
+    }
+    textDirty = false;
+}
+
+void QLabelPrivate::ensureTextLayouted() const
+{
+    if (!textLayoutDirty)
+        return;
+    ensureTextPopulated();
+    Q_Q(const QLabel);
+    if (control) {
+        QTextDocument *doc = control->document();
+        QTextOption opt = doc->defaultTextOption();
+
+        opt.setAlignment(QFlag(this->align));
+
+        if (this->align & Qt::TextWordWrap)
+            opt.setWrapMode(QTextOption::WordWrap);
+        else
+            opt.setWrapMode(QTextOption::ManualWrap);
+
+        opt.setTextDirection(q->layoutDirection());
+
+        doc->setDefaultTextOption(opt);
+
+        QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
+        fmt.setMargin(0);
+        doc->rootFrame()->setFrameFormat(fmt);
+        doc->setTextWidth(documentRect().width());
+    }
+    textLayoutDirty = false;
+}
+
+void QLabelPrivate::ensureTextControl() const
+{
+    Q_Q(const QLabel);
+    if (!isTextLabel)
+        return;
+    if (!control) {
+        control = new QTextControl(const_cast<QLabel *>(q));
+        control->document()->setUndoRedoEnabled(false);
+        control->document()->setDefaultFont(q->font());
+        control->setTextInteractionFlags(textInteractionFlags);
+        control->setOpenExternalLinks(openExternalLinks);
+        control->setPalette(q->palette());
+        control->setFocus(q->hasFocus());
+        QObject::connect(control, SIGNAL(updateRequest(QRectF)),
+                         q, SLOT(update()));
+        QObject::connect(control, SIGNAL(linkHovered(QString)),
+                         q, SLOT(_q_linkHovered(QString)));
+        QObject::connect(control, SIGNAL(linkActivated(QString)),
+                         q, SIGNAL(linkActivated(QString)));
+        textLayoutDirty = true;
+        textDirty = true;
+    }
+}
+
+void QLabelPrivate::sendControlEvent(QEvent *e)
+{
+    Q_Q(QLabel);
+    if (!isTextLabel || !control || textInteractionFlags == Qt::NoTextInteraction) {
+        e->ignore();
+        return;
+    }
+    control->processEvent(e, -layoutRect().topLeft(), q);
+}
+
+void QLabelPrivate::_q_linkHovered(const QString &anchor)
+{
+    Q_Q(QLabel);
+#ifndef QT_NO_CURSOR
+    if (anchor.isEmpty()) { // restore cursor
+        if (validCursor)
+            q->setCursor(cursor);
+        else
+            q->unsetCursor();
+        onAnchor = false;
+    } else if (!onAnchor) {
+        validCursor = q->testAttribute(Qt::WA_SetCursor);
+        if (validCursor) {
+            cursor = q->cursor();
+        }
+        q->setCursor(Qt::PointingHandCursor);
+        onAnchor = true;
+    }
+#endif
+    emit q->linkHovered(anchor);
+}
+
+// Return the layout rect - this is the rect that is given to the layout painting code
+// This may be different from the document rect since vertical alignment is not
+// done by the text layout code
+QRectF QLabelPrivate::layoutRect() const
+{
+    QRectF cr = documentRect();
+    if (!control)
+        return cr;
+    ensureTextLayouted();
+    // Caculate y position manually
+    qreal rh = control->document()->documentLayout()->documentSize().height();
+    qreal yo = 0;
+    if (align & Qt::AlignVCenter)
+        yo = qMax((cr.height()-rh)/2, qreal(0));
+    else if (align & Qt::AlignBottom)
+        yo = qMax(cr.height()-rh, qreal(0));
+    return QRectF(cr.x(), yo + cr.y(), cr.width(), cr.height());
+}
+
+// Returns the point in the document rect adjusted with p
+QPoint QLabelPrivate::layoutPoint(const QPoint& p) const
+{
+    QRect lr = layoutRect().toRect();
+    return p - lr.topLeft();
+}
+
+#ifndef QT_NO_CONTEXTMENU
+QMenu *QLabelPrivate::createStandardContextMenu(const QPoint &pos)
+{
+    QString linkToCopy;
+    QPoint p;
+    if (control && isRichText) {
+        p = layoutPoint(pos);
+        linkToCopy = control->document()->documentLayout()->anchorAt(p);
+    }
+
+    if (linkToCopy.isEmpty() && !control)
+        return 0;
+
+    return control->createStandardContextMenu(p, q_func());
+}
+#endif
+
+/*!
+    \fn void QLabel::linkHovered(const QString &link)
+    \since 4.2
+
+    This signal is emitted when the user hovers over a link. The URL
+    referred to by the anchor is passed in \a link.
+
+    \sa linkActivated()
+*/
+
+
+/*!
+    \fn void QLabel::linkActivated(const QString &link)
+    \since 4.2
+
+    This signal is emitted when the user clicks a link. The URL
+    referred to by the anchor is passed in \a link.
+
+    \sa linkHovered()
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qlabel.cpp"