src/gui/widgets/qlabel.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtGui module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qpainter.h"
00025 #include "qevent.h"
00026 #include "qdrawutil.h"
00027 #include "qapplication.h"
00028 #include "qabstractbutton.h"
00029 #include "qstyle.h"
00030 #include "qstyleoption.h"
00031 #include <limits.h>
00032 #include "qaction.h"
00033 #include "qclipboard.h"
00034 #include <qdebug.h>
00035 #include <qurl.h>
00036 #include "qlabel_p.h"
00037 
00121 #ifndef QT_NO_PICTURE
00122 
00127 const QPicture *QLabel::picture() const
00128 {
00129     Q_D(const QLabel);
00130     return d->picture;
00131 }
00132 #endif
00133 
00134 
00143 QLabel::QLabel(QWidget *parent, Qt::WindowFlags f)
00144     : QFrame(*new QLabelPrivate(), parent, f)
00145 {
00146     Q_D(QLabel);
00147     d->init();
00148 }
00149 
00158 QLabel::QLabel(const QString &text, QWidget *parent, Qt::WindowFlags f)
00159         : QFrame(*new QLabelPrivate(), parent, f)
00160 {
00161     Q_D(QLabel);
00162     d->init();
00163     setText(text);
00164 }
00165 
00166 
00167 #ifdef QT3_SUPPORT
00168 
00177 QLabel::QLabel(QWidget *parent, const char *name, Qt::WindowFlags f)
00178     : QFrame(*new QLabelPrivate(), parent, f)
00179 {
00180     Q_D(QLabel);
00181     if (name)
00182         setObjectName(QString::fromAscii(name));
00183     d->init();
00184 }
00185 
00186 
00196 QLabel::QLabel(const QString &text, QWidget *parent, const char *name,
00197                 Qt::WindowFlags f)
00198         : QFrame(*new QLabelPrivate(), parent, f)
00199 {
00200     Q_D(QLabel);
00201     if (name)
00202         setObjectName(QString::fromAscii(name));
00203     d->init();
00204     setText(text);
00205 }
00206 
00207 
00223 QLabel::QLabel(QWidget *buddy, const QString &text,
00224                 QWidget *parent, const char *name, Qt::WindowFlags f)
00225     : QFrame(*new QLabelPrivate(), parent, f)
00226 {
00227     Q_D(QLabel);
00228     if (name)
00229         setObjectName(QString::fromAscii(name));
00230     d->init();
00231 #ifndef QT_NO_SHORTCUT
00232     setBuddy(buddy);
00233 #endif
00234     setText(text);
00235 }
00236 #endif //QT3_SUPPORT
00237 
00242 QLabel::~QLabel()
00243 {
00244     Q_D(QLabel);
00245     d->clearContents();
00246 }
00247 
00248 void QLabelPrivate::init()
00249 {
00250     Q_Q(QLabel);
00251 
00252     valid_hints = false;
00253     margin = 0;
00254 #ifndef QT_NO_MOVIE
00255     movie = 0;
00256 #endif
00257 #ifndef QT_NO_SHORTCUT
00258     shortcutId = -1;
00259 #endif
00260     pixmap = 0;
00261     scaledpixmap = 0;
00262     cachedimage = 0;
00263 #ifndef QT_NO_PICTURE
00264     picture = 0;
00265 #endif
00266     align = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextExpandTabs;
00267     indent = -1;
00268     scaledcontents = false;
00269     textDirty = false;
00270     textformat = Qt::AutoText;
00271     doc = 0;
00272     control = 0;
00273     textInteractionFlags = Qt::LinksAccessibleByMouse;
00274 
00275     q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
00276 
00277     hasCustomCursor = false;
00278     openExternalLinks = false;
00279 }
00280 
00281 
00309 void QLabel::setText(const QString &text)
00310 {
00311     Q_D(QLabel);
00312     if (d->text == text)
00313         return;
00314     d->clearContents();
00315     d->text = text;
00316     if (!d->doc) {
00317         d->doc = new QTextDocument(this);
00318         d->doc->setUndoRedoEnabled(false);
00319         d->doc->setDefaultFont(font());
00320     }
00321 
00322     if (d->isRichText()) {
00323         d->doc->setHtml(text);
00324         setMouseTracking(true);
00325         d->ensureTextControl();
00326     } else {
00327         d->doc->setPlainText(text);
00328         setMouseTracking(false);
00329 #ifndef QT_NO_SHORTCUT
00330         if (d->buddy)
00331             d->updateShortcut();
00332 #endif
00333     }
00334 
00335     d->updateLabel();
00336 }
00337 
00338 QString QLabel::text() const
00339 {
00340     Q_D(const QLabel);
00341     return d->text;
00342 }
00343 
00348 void QLabel::clear()
00349 {
00350     Q_D(QLabel);
00351     d->clearContents();
00352     d->updateLabel();
00353 }
00354 
00364 void QLabel::setPixmap(const QPixmap &pixmap)
00365 {
00366     Q_D(QLabel);
00367     if (!d->pixmap || d->pixmap->serialNumber() != pixmap.serialNumber()) {
00368         d->clearContents();
00369         d->pixmap = new QPixmap(pixmap);
00370     }
00371 
00372     if (d->pixmap->depth() == 1 && !d->pixmap->mask())
00373         d->pixmap->setMask(*((QBitmap *)d->pixmap));
00374 
00375     d->updateLabel();
00376 }
00377 
00378 const QPixmap *QLabel::pixmap() const
00379 {
00380     Q_D(const QLabel);
00381     return d->pixmap;
00382 }
00383 
00384 #ifndef QT_NO_PICTURE
00385 
00394 void QLabel::setPicture(const QPicture &picture)
00395 {
00396     Q_D(QLabel);
00397     d->clearContents();
00398     d->picture = new QPicture(picture);
00399 
00400     d->updateLabel();
00401 }
00402 #endif // QT_NO_PICTURE
00403 
00417 void QLabel::setNum(int num)
00418 {
00419     QString str;
00420     str.setNum(num);
00421     setText(str);
00422 }
00423 
00439 void QLabel::setNum(double num)
00440 {
00441     QString str;
00442     str.setNum(num);
00443     setText(str);
00444 }
00445 
00453 void QLabel::setAlignment(Qt::Alignment alignment)
00454 {
00455     Q_D(QLabel);
00456     if (alignment == (d->align & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask)))
00457         return;
00458     d->align = (d->align & ~(Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask))
00459                | (alignment & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask));
00460 
00461     d->updateLabel();
00462 }
00463 
00464 #ifdef QT3_SUPPORT
00465 
00471 void QLabel::setAlignment(int alignment)
00472 {
00473     Q_D(QLabel);
00474     d->align = alignment & ~(Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask|Qt::TextWordWrap);
00475     setAlignment(Qt::Alignment(QFlag(alignment)));
00476 }
00477 #endif
00478 
00479 Qt::Alignment QLabel::alignment() const
00480 {
00481     Q_D(const QLabel);
00482     return QFlag(d->align & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask));
00483 }
00484 
00485 
00493 void QLabel::setWordWrap(bool on)
00494 {
00495     Q_D(QLabel);
00496     if (on)
00497         d->align |= Qt::TextWordWrap;
00498     else
00499         d->align &= ~Qt::TextWordWrap;
00500 
00501     d->updateLabel();
00502 }
00503 
00504 bool QLabel::wordWrap() const
00505 {
00506     Q_D(const QLabel);
00507     return d->align & Qt::TextWordWrap;
00508 }
00509 
00528 void QLabel::setIndent(int indent)
00529 {
00530     Q_D(QLabel);
00531     d->indent = indent;
00532     d->updateLabel();
00533 }
00534 
00535 int QLabel::indent() const
00536 {
00537     Q_D(const QLabel);
00538     return d->indent;
00539 }
00540 
00541 
00553 int QLabel::margin() const
00554 {
00555     Q_D(const QLabel);
00556     return d->margin;
00557 }
00558 
00559 void QLabel::setMargin(int margin)
00560 {
00561     Q_D(QLabel);
00562     if (d->margin == margin)
00563         return;
00564     d->margin = margin;
00565     d->updateLabel();
00566 }
00567 
00572 QSize QLabelPrivate::sizeForWidth(int w) const
00573 {
00574     Q_Q(const QLabel);
00575     QSize contentsMargin(leftmargin + rightmargin, topmargin + bottommargin);
00576 
00577     QRect br;
00578 
00579     int hextra = 2 * margin;
00580     int vextra = hextra;
00581 
00582     if (pixmap)
00583         br = pixmap->rect();
00584 #ifndef QT_NO_PICTURE
00585     else if (picture)
00586         br = picture->boundingRect();
00587 #endif
00588 #ifndef QT_NO_MOVIE
00589     else if (movie)
00590         br = movie->currentPixmap().rect();
00591 #endif
00592     else if (doc) {
00593         ensureTextLayouted();
00594         const qreal oldTextWidth = doc->textWidth();
00595         // Add indentation
00596         QFontMetrics fm(q->fontMetrics());
00597         int m = indent;
00598 
00599         if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
00600             m = fm.width(QLatin1Char('x')) - margin*2;
00601         if (m > 0) {
00602             int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align));
00603             if ((align & Qt::AlignLeft) || (align & Qt::AlignRight))
00604                 hextra += m;
00605             if ((align & Qt::AlignTop) || (align & Qt::AlignBottom))
00606                 vextra += m;
00607         }
00608 
00609         // Calculate the length of document if w is the width
00610         if (align & Qt::TextWordWrap) {
00611             if (w >= 0) {
00612                 w = qMax(w-hextra-contentsMargin.width(), 0); // strip margin and indent
00613                 doc->setTextWidth(w);
00614             } else {
00615                 doc->adjustSize();
00616             }
00617         } else {
00618             doc->setTextWidth(-1);
00619         }
00620         br = QRect(QPoint(0, 0), doc->size().toSize());
00621 
00622         // restore state
00623         doc->setTextWidth(oldTextWidth);
00624     } else {
00625         QFontMetrics fm = q->fontMetrics();
00626         br = QRect(QPoint(0, 0), QSize(fm.averageCharWidth(), fm.lineSpacing()));
00627     }
00628 
00629     const QSize contentsSize(br.width() + hextra, br.height() + vextra);
00630     return contentsSize + contentsMargin;
00631 }
00632 
00633 
00638 int QLabel::heightForWidth(int w) const
00639 {
00640     Q_D(const QLabel);
00641     if (d->doc)
00642         return d->sizeForWidth(w).height();
00643     return QWidget::heightForWidth(w);
00644 }
00645 
00661 bool QLabel::openExternalLinks() const
00662 {
00663     Q_D(const QLabel);
00664     return d->openExternalLinks;
00665 }
00666 
00667 void QLabel::setOpenExternalLinks(bool open)
00668 {
00669     Q_D(QLabel);
00670     d->openExternalLinks = open;
00671     if (d->control)
00672         d->control->setOpenExternalLinks(open);
00673 }
00674 
00687 void QLabel::setTextInteractionFlags(Qt::TextInteractionFlags flags)
00688 {
00689     Q_D(QLabel);
00690     d->textInteractionFlags = flags;
00691     if (flags & Qt::LinksAccessibleByKeyboard)
00692         setFocusPolicy(Qt::StrongFocus);
00693     else if (flags & Qt::TextSelectableByKeyboard)
00694         setFocusPolicy(Qt::ClickFocus);
00695     else
00696         setFocusPolicy(Qt::NoFocus);
00697     if (d->control)
00698         d->control->setTextInteractionFlags(flags);
00699 }
00700 
00701 Qt::TextInteractionFlags QLabel::textInteractionFlags() const
00702 {
00703     Q_D(const QLabel);
00704     return d->textInteractionFlags;
00705 }
00706 
00709 QSize QLabel::sizeHint() const
00710 {
00711     Q_D(const QLabel);
00712     if (!d->valid_hints)
00713         (void) QLabel::minimumSizeHint();
00714     return d->sh;
00715 }
00716 
00720 QSize QLabel::minimumSizeHint() const
00721 {
00722     Q_D(const QLabel);
00723     if (d->valid_hints) {
00724         if (d->sizePolicy == sizePolicy())
00725             return d->msh;
00726     }
00727 
00728     ensurePolished();
00729     d->valid_hints = true;
00730     d->sh = d->sizeForWidth(-1); // wrap ? golden ratio : min doc size
00731     QSize msh(-1, -1);
00732 
00733     if (!d->doc) {
00734         msh = d->sh;
00735     } else {
00736         msh.rheight() = d->sizeForWidth(QWIDGETSIZE_MAX).height(); // height for one line
00737         msh.rwidth() = d->sizeForWidth(0).width(); // wrap ? size of biggest word : min doc size
00738         if (d->sh.height() < msh.height())
00739             msh.rheight() = d->sh.height();
00740     }
00741     d->msh = msh;
00742     d->sizePolicy = sizePolicy();
00743     return msh;
00744 }
00745 
00748 void QLabel::mousePressEvent(QMouseEvent *ev)
00749 {
00750     Q_D(QLabel);
00751     if (!d->doc) {
00752         ev->ignore();
00753         return;
00754     }
00755 
00756     d->sendControlEvent(ev);
00757 }
00758 
00761 void QLabel::mouseMoveEvent(QMouseEvent *ev)
00762 {
00763     Q_D(QLabel);
00764     if (!d->doc) {
00765         ev->ignore();
00766         return;
00767     }
00768 
00769     d->sendControlEvent(ev);
00770 }
00771 
00774 void QLabel::mouseReleaseEvent(QMouseEvent *ev)
00775 {
00776     Q_D(QLabel);
00777     if (!d->doc) {
00778         ev->ignore();
00779         return;
00780     }
00781 
00782     d->sendControlEvent(ev);
00783 }
00784 
00787 void QLabel::contextMenuEvent(QContextMenuEvent *ev)
00788 {
00789 #ifdef QT_NO_CONTEXTMENU
00790     Q_UNUSED(ev);
00791 #else
00792     Q_D(QLabel);
00793     if (!d->doc) {
00794         ev->ignore();
00795         return;
00796     }
00797     QMenu *menu = d->createStandardContextMenu(ev->pos());
00798     if (!menu) {
00799         ev->ignore();
00800         return;
00801     }
00802     ev->accept();
00803     menu->exec(ev->globalPos());
00804     delete menu;
00805 #endif
00806 }
00807 
00811 void QLabel::focusInEvent(QFocusEvent *ev)
00812 {
00813     Q_D(QLabel);
00814     if (d->doc) {
00815         d->ensureTextControl();
00816         d->sendControlEvent(ev);
00817     }
00818     QFrame::focusInEvent(ev);
00819 }
00820 
00824 void QLabel::focusOutEvent(QFocusEvent *ev)
00825 {
00826     Q_D(QLabel);
00827     d->sendControlEvent(ev);
00828     QFrame::focusOutEvent(ev);
00829 }
00830 
00833 bool QLabel::focusNextPrevChild(bool next)
00834 {
00835     Q_D(QLabel);
00836     if (d->control && d->control->setFocusToNextOrPreviousAnchor(next))
00837         return true;
00838     return QFrame::focusNextPrevChild(next);
00839 }
00840 
00843 void QLabel::keyPressEvent(QKeyEvent *ev)
00844 {
00845     Q_D(QLabel);
00846     d->sendControlEvent(ev);
00847 }
00848 
00851 bool QLabel::event(QEvent *e)
00852 {
00853     Q_D(QLabel);
00854     QEvent::Type type = e->type();
00855 
00856 #ifndef QT_NO_SHORTCUT
00857     if (type == QEvent::Shortcut) {
00858         QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
00859         if (se->shortcutId() == d->shortcutId) {
00860             QWidget * w = d->buddy;
00861             QAbstractButton *button = qobject_cast<QAbstractButton *>(w);
00862             if (w->focusPolicy() != Qt::NoFocus)
00863                 w->setFocus(Qt::ShortcutFocusReason);
00864             if (button && !se->isAmbiguous())
00865                 button->animateClick();
00866             else
00867                 window()->setAttribute(Qt::WA_KeyboardFocusChange);
00868             return true;
00869         }
00870     } else
00871 #endif
00872     if (type == QEvent::Resize && d->doc) {
00873         d->textDirty = true;
00874     } else if (e->type() == QEvent::StyleChange) {
00875         d->updateLabel();
00876     }
00877 
00878     return QFrame::event(e);
00879 }
00880 
00883 void QLabel::paintEvent(QPaintEvent *)
00884 {
00885     Q_D(QLabel);
00886     QStyle *style = QWidget::style();
00887     QPainter painter(this);
00888     drawFrame(&painter);
00889     QRect cr = contentsRect();
00890     cr.adjust(d->margin, d->margin, -d->margin, -d->margin);
00891     int align = QStyle::visualAlignment(layoutDirection(), QFlag(d->align));
00892 
00893 #ifndef QT_NO_MOVIE
00894     if (d->movie) {
00895         if (d->scaledcontents)
00896             style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap().scaled(cr.size()));
00897         else
00898             style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap());
00899     }
00900     else
00901 #endif
00902     if (d->doc) {
00903         const bool underline = (bool)style->styleHint(QStyle::SH_UnderlineShortcut, 0, this, 0);
00904 #ifndef QT_NO_SHORTCUT
00905         if (d->shortcutId != -1
00906             && underline != d->shortcutCursor.charFormat().fontUnderline()) {
00907                 QTextCharFormat fmt;
00908                 fmt.setFontUnderline(underline);
00909                 d->shortcutCursor.mergeCharFormat(fmt);
00910         }
00911 #endif
00912         d->ensureTextLayouted();
00913         QAbstractTextDocumentLayout *layout = d->doc->documentLayout();
00914         QRect lr = d->layoutRect();
00915 
00916         QAbstractTextDocumentLayout::PaintContext context;
00917         QStyleOption opt(0);
00918         opt.init(this);
00919 
00920         if (!isEnabled() && style->styleHint(QStyle::SH_EtchDisabledText, &opt, this)) {
00921             context.palette = palette();
00922             context.palette.setColor(QPalette::Text, context.palette.light().color());
00923             painter.save();
00924             painter.translate(lr.x() + 1, lr.y() + 1);
00925             painter.setClipRect(lr.translated(-lr.x() - 1, -lr.y() - 1));
00926             layout->draw(&painter, context);
00927             painter.restore();
00928         }
00929 
00930         // Adjust the palette
00931         context.palette = palette();
00932         if (foregroundRole() != QPalette::Text && isEnabled())
00933             context.palette.setColor(QPalette::Text, context.palette.color(foregroundRole()));
00934 
00935         painter.save();
00936         painter.translate(lr.topLeft());
00937         painter.setClipRect(lr.translated(-lr.x(), -lr.y()));
00938         if (d->control) {
00939             d->control->setPalette(context.palette);
00940             d->control->drawContents(&painter);
00941         } else {
00942             layout->draw(&painter, context);
00943         }
00944         painter.restore();
00945     } else
00946 #ifndef QT_NO_PICTURE
00947     if (d->picture) {
00948         QRect br = d->picture->boundingRect();
00949         int rw = br.width();
00950         int rh = br.height();
00951         if (d->scaledcontents) {
00952             painter.save();
00953             painter.translate(cr.x(), cr.y());
00954             painter.scale((double)cr.width()/rw, (double)cr.height()/rh);
00955             painter.drawPicture(-br.x(), -br.y(), *d->picture);
00956             painter.restore();
00957         } else {
00958             int xo = 0;
00959             int yo = 0;
00960             if (align & Qt::AlignVCenter)
00961                 yo = (cr.height()-rh)/2;
00962             else if (align & Qt::AlignBottom)
00963                 yo = cr.height()-rh;
00964             if (align & Qt::AlignRight)
00965                 xo = cr.width()-rw;
00966             else if (align & Qt::AlignHCenter)
00967                 xo = (cr.width()-rw)/2;
00968             painter.drawPicture(cr.x()+xo-br.x(), cr.y()+yo-br.y(), *d->picture);
00969         }
00970     } else
00971 #endif
00972     if (d->pixmap && !d->pixmap->isNull()) {
00973         QPixmap pix;
00974         if (d->scaledcontents) {
00975             if (!d->scaledpixmap || d->scaledpixmap->size() != cr.size()) {
00976                 if (!d->cachedimage)
00977                     d->cachedimage = new QImage(d->pixmap->toImage());
00978                 delete d->scaledpixmap;
00979                 d->scaledpixmap = new QPixmap(QPixmap::fromImage(d->cachedimage->scaled(cr.size(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)));
00980             }
00981             pix = *d->scaledpixmap;
00982         } else
00983             pix = *d->pixmap;
00984         QStyleOption opt;
00985         opt.initFrom(this);
00986         if (!isEnabled())
00987             pix = style->generatedIconPixmap(QIcon::Disabled, pix, &opt);
00988         style->drawItemPixmap(&painter, cr, align, pix);
00989     }
00990 }
00991 
00992 
00997 void QLabelPrivate::updateLabel()
00998 {
00999     Q_Q(QLabel);
01000     valid_hints = false;
01001 
01002     if (doc) {
01003         QSizePolicy policy = q->sizePolicy();
01004         const bool wrap = align & Qt::TextWordWrap;
01005         policy.setHeightForWidth(wrap);
01006         if (policy != q->sizePolicy())
01007             q->setSizePolicy(policy);
01008         textDirty = true;
01009     }
01010     q->updateGeometry();
01011     q->update(q->contentsRect());
01012 }
01013 
01014 #ifndef QT_NO_SHORTCUT
01015 
01050 void QLabel::setBuddy(QWidget *buddy)
01051 {
01052     Q_D(QLabel);
01053     d->buddy = buddy;
01054     if (d->doc && !d->isRichText()) {
01055         releaseShortcut(d->shortcutId);
01056         d->shortcutId = -1;
01057         d->doc->setPlainText(d->text); // restore the old text
01058         if (buddy)
01059             d->updateShortcut(); // grab new shortcut
01060         d->updateLabel();
01061     }
01062 }
01063 
01064 
01071 QWidget * QLabel::buddy() const
01072 {
01073     Q_D(const QLabel);
01074     return d->buddy;
01075 }
01076 
01077 void QLabelPrivate::updateShortcut()
01078 {
01079     Q_Q(QLabel);
01080     Q_ASSERT(shortcutId == -1);
01081     Q_ASSERT(!isRichText());
01082 
01083     // Underline the first character that follows an ampersand
01084     shortcutCursor = doc->find(QLatin1String("&"));
01085     if (shortcutCursor.isNull())
01086         return;
01087     shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
01088     shortcutCursor.deleteChar(); // remove the ampersand
01089     shortcutCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
01090 }
01091 
01092 #endif // QT_NO_SHORTCUT
01093 
01094 #ifndef QT_NO_MOVIE
01095 void QLabelPrivate::_q_movieUpdated(const QRect& rect)
01096 {
01097     Q_Q(QLabel);
01098     if (movie && movie->isValid()) {
01099         QRect r;
01100         if (scaledcontents) {
01101             QRect cr = q->contentsRect();
01102             QRect pixmapRect(cr.topLeft(), movie->currentPixmap().size());
01103             if (pixmapRect.isEmpty())
01104                 return;
01105             r.setRect(cr.left(), cr.top(),
01106                       (rect.width() * cr.width()) / pixmapRect.width(),
01107                       (rect.height() * cr.height()) / pixmapRect.height());
01108         } else {
01109             r = q->style()->itemPixmapRect(q->contentsRect(), align, movie->currentPixmap());
01110             r.translate(rect.x(), rect.y());
01111             r.setWidth(qMin(r.width(), rect.width()));
01112             r.setHeight(qMin(r.height(), rect.height()));
01113         }
01114         q->update(r);
01115     }
01116 }
01117 
01118 void QLabelPrivate::_q_movieResized(const QSize& size)
01119 {
01120     Q_Q(QLabel);
01121     valid_hints = false;
01122     _q_movieUpdated(QRect(QPoint(0,0), size));
01123     q->updateGeometry();
01124 }
01125 
01137 void QLabel::setMovie(QMovie *movie)
01138 {
01139     Q_D(QLabel);
01140     d->clearContents();
01141 
01142     if (!movie)
01143         return;
01144 
01145     d->movie = movie;
01146     connect(movie, SIGNAL(resized(QSize)), this, SLOT(_q_movieResized(QSize)));
01147     connect(movie, SIGNAL(updated(QRect)), this, SLOT(_q_movieUpdated(QRect)));
01148 
01149     // Assume that if the movie is running,
01150     // resize/update signals will come soon enough
01151     if (movie->state() != QMovie::Running)
01152         d->updateLabel();
01153 }
01154 
01155 #endif // QT_NO_MOVIE
01156 
01163 void QLabelPrivate::clearContents()
01164 {
01165     delete control;
01166     control = 0;
01167     delete doc;
01168     doc = 0;
01169 
01170 #ifndef QT_NO_PICTURE
01171     delete picture;
01172     picture = 0;
01173 #endif
01174     delete scaledpixmap;
01175     scaledpixmap = 0;
01176     delete cachedimage;
01177     cachedimage = 0;
01178     delete pixmap;
01179     pixmap = 0;
01180 
01181     text.clear();
01182     Q_Q(QLabel);
01183 #ifndef QT_NO_SHORTCUT
01184     q->releaseShortcut(shortcutId);
01185     shortcutId = -1;
01186 #endif
01187 #ifndef QT_NO_MOVIE
01188     if (movie) {
01189         QObject::disconnect(movie, SIGNAL(resized(QSize)), q, SLOT(_q_movieResized(QSize)));
01190         QObject::disconnect(movie, SIGNAL(updated(QRect)), q, SLOT(_q_movieUpdated(QRect)));
01191     }
01192     movie = 0;
01193 #endif
01194 }
01195 
01196 
01197 #ifndef QT_NO_MOVIE
01198 
01206 QMovie *QLabel::movie() const
01207 {
01208     Q_D(const QLabel);
01209     return d->movie;
01210 }
01211 
01212 #endif  // QT_NO_MOVIE
01213 
01226 Qt::TextFormat QLabel::textFormat() const
01227 {
01228     Q_D(const QLabel);
01229     return d->textformat;
01230 }
01231 
01232 void QLabel::setTextFormat(Qt::TextFormat format)
01233 {
01234     Q_D(QLabel);
01235     if (format != d->textformat) {
01236         d->textformat = format;
01237         QString t = d->text;
01238         if (!t.isNull()) {
01239             d->text.clear();
01240             setText(t);
01241         }
01242     }
01243 }
01244 
01248 void QLabel::changeEvent(QEvent *ev)
01249 {
01250     Q_D(QLabel);
01251     if(ev->type() == QEvent::FontChange || ev->type() == QEvent::ApplicationFontChange) {
01252         if (d->doc) {
01253             d->doc->setDefaultFont(font());
01254             d->updateLabel();
01255         }
01256     } else if (ev->type() == QEvent::PaletteChange && d->control) {
01257         d->control->setPalette(palette());
01258     }
01259     QFrame::changeEvent(ev);
01260 }
01261 
01272 bool QLabel::hasScaledContents() const
01273 {
01274     Q_D(const QLabel);
01275     return d->scaledcontents;
01276 }
01277 
01278 void QLabel::setScaledContents(bool enable)
01279 {
01280     Q_D(QLabel);
01281     if ((bool)d->scaledcontents == enable)
01282         return;
01283     d->scaledcontents = enable;
01284     if (!enable) {
01285         delete d->scaledpixmap;
01286         d->scaledpixmap = 0;
01287         delete d->cachedimage;
01288         d->cachedimage = 0;
01289     }
01290     update(contentsRect());
01291 }
01292 
01293 
01303 // Returns the rect that is available for us to draw the document
01304 QRect QLabelPrivate::documentRect() const
01305 {
01306     Q_Q(const QLabel);
01307     Q_ASSERT_X(doc, "documentRect", "document rect called when doc not set!");
01308     QRect cr = q->contentsRect();
01309     cr.adjust(margin, margin, -margin, -margin);
01310     const int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align));
01311     int m = indent;
01312     if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
01313         m = q->fontMetrics().width(QLatin1Char('x')) / 2 - margin;
01314     if (m > 0) {
01315         if (align & Qt::AlignLeft)
01316             cr.setLeft(cr.left() + m);
01317         if (align & Qt::AlignRight)
01318             cr.setRight(cr.right() - m);
01319         if (align & Qt::AlignTop)
01320             cr.setTop(cr.top() + m);
01321         if (align & Qt::AlignBottom)
01322             cr.setBottom(cr.bottom() - m);
01323     }
01324     return cr;
01325 }
01326 
01327 void QLabelPrivate::ensureTextLayouted() const
01328 {
01329     if (!textDirty)
01330         return;
01331     Q_Q(const QLabel);
01332     if (doc) {
01333         QTextDocumentLayout *lout = qobject_cast<QTextDocumentLayout *>(doc->documentLayout());
01334         Q_ASSERT(lout);
01335 
01336         const bool wrap = align & Qt::TextWordWrap;
01337         int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align));
01338         int flags = (wrap? 0 : Qt::TextSingleLine) | align;
01339         flags |= (q->layoutDirection() == Qt::RightToLeft) ? QTextDocumentLayout::RTL : QTextDocumentLayout::LTR;
01340         lout->setBlockTextFlags(flags);
01341 
01342         if (wrap) {
01343             // ensure that we break at words and not just about anywhere
01344             lout->setWordWrapMode(QTextOption::WordWrap);
01345         }
01346 
01347         QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
01348         fmt.setMargin(0);
01349         doc->rootFrame()->setFrameFormat(fmt);
01350         doc->setTextWidth(documentRect().width());
01351     }
01352     textDirty = false;
01353 }
01354 
01355 void QLabelPrivate::ensureTextControl()
01356 {
01357     Q_Q(QLabel);
01358     if (control || !doc)
01359         return;
01360     ensureTextLayouted();
01361     control = new QTextControl(doc, q);
01362     control->setTextInteractionFlags(textInteractionFlags);
01363     control->setOpenExternalLinks(openExternalLinks);
01364     control->setPalette(q->palette());
01365     control->setFocus(q->hasFocus());
01366     QObject::connect(control, SIGNAL(updateRequest(QRectF)),
01367                      q, SLOT(update()));
01368     QObject::connect(control, SIGNAL(linkHovered(QString)),
01369                      q, SLOT(_q_linkHovered(QString)));
01370     QObject::connect(control, SIGNAL(linkActivated(QString)),
01371                      q, SIGNAL(linkActivated(QString)));
01372 }
01373 
01374 void QLabelPrivate::sendControlEvent(QEvent *e)
01375 {
01376     Q_Q(QLabel);
01377     if (!control) {
01378         e->ignore();
01379         return;
01380     }
01381     control->processEvent(e, -layoutRect().topLeft(), q);
01382 }
01383 
01384 void QLabelPrivate::_q_linkHovered(const QString &anchor)
01385 {
01386     Q_Q(QLabel);
01387     if (anchor.isEmpty()) { // restore cursor
01388 #ifndef QT_NO_CURSOR
01389         q->setCursor(hasCustomCursor ? cursor : Qt::ArrowCursor);
01390 #endif
01391     } else {
01392 #ifndef QT_NO_CURSOR
01393         hasCustomCursor = q->testAttribute(Qt::WA_SetCursor);
01394         if (hasCustomCursor)
01395             cursor = q->cursor();
01396         q->setCursor(Qt::PointingHandCursor);
01397 #endif
01398     }
01399     emit q->linkHovered(anchor);
01400 }
01401 
01402 // Return the layout rect - this is the rect that is given to the layout painting code
01403 // This may be different from the document rect since vertical alignment is not
01404 // done by the text layout code
01405 QRect QLabelPrivate::layoutRect() const
01406 {
01407     ensureTextLayouted();
01408     QRect cr = documentRect();
01409     // Caculate y position manually
01410     int rh = qRound(doc->documentLayout()->documentSize().height());
01411     int yo = 0;
01412     if (align & Qt::AlignVCenter)
01413         yo = qMax((cr.height()-rh)/2, 0);
01414     else if (align & Qt::AlignBottom)
01415         yo = qMax(cr.height()-rh, 0);
01416     return QRect(cr.x(), yo + cr.y(), cr.width(), cr.height());
01417 }
01418 
01419 // Returns the point in the document rect adjusted with p
01420 QPoint QLabelPrivate::layoutPoint(const QPoint& p) const
01421 {
01422     QRect lr = layoutRect();
01423     return p - lr.topLeft();
01424 }
01425 
01426 #ifndef QT_NO_CONTEXTMENU
01427 QMenu *QLabelPrivate::createStandardContextMenu(const QPoint &pos)
01428 {
01429     QString linkToCopy;
01430     QPoint p;
01431     if (isRichText()) {
01432         p = layoutPoint(pos);
01433         linkToCopy = doc->documentLayout()->anchorAt(p);
01434     }
01435 
01436     if (linkToCopy.isEmpty() && !control)
01437         return 0;
01438 
01439     return control->createStandardContextMenu(p, q_func());
01440 }
01441 #endif
01442 
01464 #include "moc_qlabel.cpp"

Generated on Thu Mar 15 11:56:57 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1