summaryrefslogtreecommitdiffstats
path: root/src/gui/widgets/qlabel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/widgets/qlabel.cpp')
-rw-r--r--src/gui/widgets/qlabel.cpp1718
1 files changed, 1718 insertions, 0 deletions
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp
new file mode 100644
index 0000000000..4714d2f2c9
--- /dev/null
+++ b/src/gui/widgets/qlabel.cpp
@@ -0,0 +1,1718 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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"
+#include <qmath.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(textDirection(), 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);
+ }
+
+ QSizeF controlSize = control->size();
+ br = QRect(QPoint(0, 0), QSize(qCeil(controlSize.width()), qCeil(controlSize.height())));
+
+ // 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 = qMin(fm.averageCharWidth() * 80, q->maximumSize().width());
+ 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;
+}
+
+/*!
+ Selects text from position \a start and for \a length characters.
+
+ \sa selectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+void QLabel::setSelection(int start, int length)
+{
+ Q_D(QLabel);
+ if (d->control) {
+ d->ensureTextPopulated();
+ QTextCursor cursor = d->control->textCursor();
+ cursor.setPosition(start);
+ cursor.setPosition(start + length, QTextCursor::KeepAnchor);
+ d->control->setTextCursor(cursor);
+ }
+}
+
+/*!
+ \property QLabel::hasSelectedText
+ \brief whether there is any text selected
+
+ hasSelectedText() returns true if some or all of the text has been
+ selected by the user; otherwise returns false.
+
+ By default, this property is false.
+
+ \sa selectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+bool QLabel::hasSelectedText() const
+{
+ Q_D(const QLabel);
+ if (d->control)
+ return d->control->textCursor().hasSelection();
+ return false;
+}
+
+/*!
+ \property QLabel::selectedText
+ \brief the selected text
+
+ If there is no selected text this property's value is
+ an empty string.
+
+ By default, this property contains an empty string.
+
+ \sa hasSelectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+QString QLabel::selectedText() const
+{
+ Q_D(const QLabel);
+ if (d->control)
+ return d->control->textCursor().selectedText();
+ return QString();
+}
+
+/*!
+ selectionStart() returns the index of the first selected character in the
+ label or -1 if no text is selected.
+
+ \sa selectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+int QLabel::selectionStart() const
+{
+ Q_D(const QLabel);
+ if (d->control && d->control->textCursor().hasSelection())
+ return d->control->textCursor().selectionStart();
+ return -1;
+}
+
+/*!\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->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(ev->globalPos());
+#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(d->isTextLabel ? d->textDirection()
+ : 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().toAlignedRect();
+ 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 | (d->textDirection() == Qt::LeftToRight ? Qt::TextForceLeftToRight
+ : Qt::TextForceRightToLeft);
+ 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 (!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();
+ }
+ 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());
+}
+
+Qt::LayoutDirection QLabelPrivate::textDirection() const
+{
+ if (control) {
+ QTextOption opt = control->document()->defaultTextOption();
+ return opt.textDirection();
+ }
+
+ return text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight;
+}
+
+/*!
+ \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(isTextLabel ? textDirection()
+ : 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);
+
+#ifndef QT_NO_SHORTCUT
+ if (hasShortcut) {
+ // Underline the first character that follows an ampersand (and remove the others ampersands)
+ int from = 0;
+ bool found = false;
+ QTextCursor cursor;
+ while (!(cursor = control->document()->find((QLatin1String("&")), from)).isNull()) {
+ cursor.deleteChar(); // remove the ampersand
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ from = cursor.position();
+ if (!found && cursor.selectedText() != QLatin1String("&")) { //not a second &
+ found = true;
+ shortcutCursor = cursor;
+ }
+ }
+ }
+#endif
+ }
+ }
+ textDirty = false;
+}
+
+void QLabelPrivate::ensureTextLayouted() const
+{
+ if (!textLayoutDirty)
+ return;
+ ensureTextPopulated();
+ 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);
+
+ 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"