diff options
Diffstat (limited to 'src/declarative/items/qquicktext.cpp')
-rw-r--r-- | src/declarative/items/qquicktext.cpp | 1950 |
1 files changed, 0 insertions, 1950 deletions
diff --git a/src/declarative/items/qquicktext.cpp b/src/declarative/items/qquicktext.cpp deleted file mode 100644 index 630b466d80..0000000000 --- a/src/declarative/items/qquicktext.cpp +++ /dev/null @@ -1,1950 +0,0 @@ -/**************************************************************************** -** -** 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 QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquicktext_p.h" -#include "qquicktext_p_p.h" - -#include <private/qsgcontext_p.h> -#include <private/qsgadaptationlayer_p.h> -#include "qquicktextnode_p.h" -#include "qquickimage_p_p.h" -#include <private/qsgtexture_p.h> - -#include <QtDeclarative/qdeclarativeinfo.h> -#include <QtGui/qevent.h> -#include <QtGui/qabstracttextdocumentlayout.h> -#include <QtGui/qpainter.h> -#include <QtGui/qtextdocument.h> -#include <QtGui/qtextobject.h> -#include <QtGui/qtextcursor.h> -#include <QtGui/qguiapplication.h> - -#include <private/qdeclarativestyledtext_p.h> -#include <private/qdeclarativepixmapcache_p.h> - -#include <qmath.h> -#include <limits.h> - -QT_BEGIN_NAMESPACE - -extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled; - -class QQuickTextDocumentWithImageResources : public QTextDocument { - Q_OBJECT - -public: - QQuickTextDocumentWithImageResources(QQuickText *parent); - virtual ~QQuickTextDocumentWithImageResources(); - - void setText(const QString &); - int resourcesLoading() const { return outstanding; } - -protected: - QVariant loadResource(int type, const QUrl &name); - -private slots: - void requestFinished(); - -private: - QHash<QUrl, QDeclarativePixmap *> m_resources; - - int outstanding; - static QSet<QUrl> errors; -}; - -DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) -DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE); - -QString QQuickTextPrivate::elideChar = QString(0x2026); - -QQuickTextPrivate::QQuickTextPrivate() -: color((QRgb)0), style(QQuickText::Normal), hAlign(QQuickText::AlignLeft), - vAlign(QQuickText::AlignTop), elideMode(QQuickText::ElideNone), - format(QQuickText::AutoText), wrapMode(QQuickText::NoWrap), lineHeight(1), - lineHeightMode(QQuickText::ProportionalHeight), lineCount(1), maximumLineCount(INT_MAX), - maximumLineCountValid(false), - texture(0), - imageCacheDirty(false), updateOnComponentComplete(true), - richText(false), styledText(false), singleline(false), cacheAllTextAsImage(true), internalWidthUpdate(false), - requireImplicitWidth(false), truncated(false), hAlignImplicit(true), rightToLeftText(false), - layoutTextElided(false), richTextAsImage(false), textureImageCacheDirty(false), textHasChanged(true), - naturalWidth(0), doc(0), elipsisLayout(0), textLine(0), nodeType(NodeIsNull) - -#if defined(Q_OS_MAC) -, layoutThread(0), paintingThread(0) -#endif - -{ - cacheAllTextAsImage = enableImageCache(); -} - -void QQuickTextPrivate::init() -{ - Q_Q(QQuickText); - q->setAcceptedMouseButtons(Qt::LeftButton); - q->setFlag(QQuickItem::ItemHasContents); -} - -QQuickTextDocumentWithImageResources::QQuickTextDocumentWithImageResources(QQuickText *parent) -: QTextDocument(parent), outstanding(0) -{ - setUndoRedoEnabled(false); -} - -QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources() -{ - if (!m_resources.isEmpty()) - qDeleteAll(m_resources); -} - -QVariant QQuickTextDocumentWithImageResources::loadResource(int type, const QUrl &name) -{ - QDeclarativeContext *context = qmlContext(parent()); - QUrl url = context->resolvedUrl(name); - - if (type == QTextDocument::ImageResource) { - QHash<QUrl, QDeclarativePixmap *>::Iterator iter = m_resources.find(url); - - if (iter == m_resources.end()) { - QDeclarativePixmap *p = new QDeclarativePixmap(context->engine(), url); - iter = m_resources.insert(url, p); - - if (p->isLoading()) { - p->connectFinished(this, SLOT(requestFinished())); - outstanding++; - } - } - - QDeclarativePixmap *p = *iter; - if (p->isReady()) { - return p->image(); - } else if (p->isError()) { - if (!errors.contains(url)) { - errors.insert(url); - qmlInfo(parent()) << p->error(); - } - } - } - - return QTextDocument::loadResource(type,url); // The *resolved* URL -} - -void QQuickTextDocumentWithImageResources::requestFinished() -{ - outstanding--; - if (outstanding == 0) { - QQuickText *textItem = static_cast<QQuickText*>(parent()); - QString text = textItem->text(); -#ifndef QT_NO_TEXTHTMLPARSER - setHtml(text); -#else - setPlainText(text); -#endif - QQuickTextPrivate *d = QQuickTextPrivate::get(textItem); - d->updateLayout(); - } -} - -void QQuickTextDocumentWithImageResources::setText(const QString &text) -{ - if (!m_resources.isEmpty()) { - qDeleteAll(m_resources); - m_resources.clear(); - outstanding = 0; - } - -#ifndef QT_NO_TEXTHTMLPARSER - setHtml(text); -#else - setPlainText(text); -#endif -} - -QSet<QUrl> QQuickTextDocumentWithImageResources::errors; - -QQuickTextPrivate::~QQuickTextPrivate() -{ - delete elipsisLayout; - delete textLine; textLine = 0; -} - -qreal QQuickTextPrivate::getImplicitWidth() const -{ - if (!requireImplicitWidth) { - // We don't calculate implicitWidth unless it is required. - // We need to force a size update now to ensure implicitWidth is calculated - QQuickTextPrivate *me = const_cast<QQuickTextPrivate*>(this); - me->requireImplicitWidth = true; - me->updateSize(); - } - return implicitWidth; -} - -void QQuickTextPrivate::updateLayout() -{ - Q_Q(QQuickText); - if (!q->isComponentComplete()) { - updateOnComponentComplete = true; - return; - } - updateOnComponentComplete = false; - layoutTextElided = false; - // Setup instance of QTextLayout for all cases other than richtext - if (!richText) { - if (elipsisLayout) { - delete elipsisLayout; - elipsisLayout = 0; - } - layout.clearLayout(); - layout.setFont(font); - if (!styledText) { - QString tmp = text; - tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); - singleline = !tmp.contains(QChar::LineSeparator); - if (singleline && !maximumLineCountValid && elideMode != QQuickText::ElideNone && q->widthValid() && wrapMode == QQuickText::NoWrap) { - QFontMetrics fm(font); - tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); - if (tmp != text) { - layoutTextElided = true; - if (!truncated) { - truncated = true; - emit q->truncatedChanged(); - } - } - } - layout.setText(tmp); - } else { - singleline = false; - if (textHasChanged) { - QDeclarativeStyledText::parse(text, layout); - textHasChanged = false; - } - } - } else { - ensureDoc(); - QTextBlockFormat::LineHeightTypes type; - type = lineHeightMode == QQuickText::FixedHeight ? QTextBlockFormat::FixedHeight : QTextBlockFormat::ProportionalHeight; - QTextBlockFormat blockFormat; - blockFormat.setLineHeight((lineHeightMode == QQuickText::FixedHeight ? lineHeight : lineHeight * 100), type); - for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) { - QTextCursor cursor(it); - cursor.mergeBlockFormat(blockFormat); - } - } - - updateSize(); -} - -void QQuickTextPrivate::updateSize() -{ - Q_Q(QQuickText); - - if (!q->isComponentComplete()) { - updateOnComponentComplete = true; - return; - } - - if (!requireImplicitWidth) { - emit q->implicitWidthChanged(); - // if the implicitWidth is used, then updateSize() has already been called (recursively) - if (requireImplicitWidth) - return; - } - - invalidateImageCache(); - - QFontMetrics fm(font); - if (text.isEmpty()) { - q->setImplicitSize(0, fm.height()); - paintedSize = QSize(0, fm.height()); - emit q->paintedSizeChanged(); - q->update(); - return; - } - - int dy = q->height(); - QSize size(0, 0); - -#if defined(Q_OS_MAC) - layoutThread = QThread::currentThread(); -#endif - - //setup instance of QTextLayout for all cases other than richtext - if (!richText) { - QRect textRect = setupTextLayout(); - layedOutTextRect = textRect; - size = textRect.size(); - dy -= size.height(); - } else { - singleline = false; // richtext can't elide or be optimized for single-line case - ensureDoc(); - doc->setDefaultFont(font); - QQuickText::HAlignment horizontalAlignment = q->effectiveHAlign(); - if (rightToLeftText) { - if (horizontalAlignment == QQuickText::AlignLeft) - horizontalAlignment = QQuickText::AlignRight; - else if (horizontalAlignment == QQuickText::AlignRight) - horizontalAlignment = QQuickText::AlignLeft; - } - QTextOption option; - option.setAlignment((Qt::Alignment)int(horizontalAlignment | vAlign)); - option.setWrapMode(QTextOption::WrapMode(wrapMode)); - if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField()) - option.setUseDesignMetrics(true); - doc->setDefaultTextOption(option); - if (requireImplicitWidth && q->widthValid()) { - doc->setTextWidth(-1); - naturalWidth = doc->idealWidth(); - } - if (wrapMode != QQuickText::NoWrap && q->widthValid()) - doc->setTextWidth(q->width()); - else - doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug) - dy -= (int)doc->size().height(); - QSize dsize = doc->size().toSize(); - layedOutTextRect = QRect(QPoint(0,0), dsize); - size = QSize(int(doc->idealWidth()),dsize.height()); - } - int yoff = 0; - - if (q->heightValid()) { - if (vAlign == QQuickText::AlignBottom) - yoff = dy; - else if (vAlign == QQuickText::AlignVCenter) - yoff = dy/2; - } - q->setBaselineOffset(fm.ascent() + yoff); - - //### need to comfirm cost of always setting these for richText - internalWidthUpdate = true; - qreal iWidth = -1; - if (!q->widthValid()) - iWidth = size.width(); - else if (requireImplicitWidth) - iWidth = naturalWidth; - if (iWidth > -1) - q->setImplicitSize(iWidth, size.height()); - internalWidthUpdate = false; - - if (iWidth == -1) - q->setImplicitHeight(size.height()); - if (paintedSize != size) { - paintedSize = size; - emit q->paintedSizeChanged(); - } - q->update(); -} - -QQuickTextLine::QQuickTextLine() - : QObject(), m_line(0), m_height(0) -{ -} - -void QQuickTextLine::setLine(QTextLine *line) -{ - m_line = line; -} - -int QQuickTextLine::number() const -{ - if (m_line) - return m_line->lineNumber(); - return 0; -} - -qreal QQuickTextLine::width() const -{ - if (m_line) - return m_line->width(); - return 0; -} - -void QQuickTextLine::setWidth(qreal width) -{ - if (m_line) - m_line->setLineWidth(width); -} - -qreal QQuickTextLine::height() const -{ - if (m_height) - return m_height; - if (m_line) - return m_line->height(); - return 0; -} - -void QQuickTextLine::setHeight(qreal height) -{ - if (m_line) - m_line->setPosition(QPointF(m_line->x(), m_line->y() - m_line->height() + height)); - m_height = height; -} - -qreal QQuickTextLine::x() const -{ - if (m_line) - return m_line->x(); - return 0; -} - -void QQuickTextLine::setX(qreal x) -{ - if (m_line) - m_line->setPosition(QPointF(x, m_line->y())); -} - -qreal QQuickTextLine::y() const -{ - if (m_line) - return m_line->y(); - return 0; -} - -void QQuickTextLine::setY(qreal y) -{ - if (m_line) - m_line->setPosition(QPointF(m_line->x(), y)); -} - -void QQuickText::doLayout() -{ - Q_D(QQuickText); - d->updateSize(); -} - -bool QQuickTextPrivate::isLineLaidOutConnected() -{ - static int idx = this->signalIndex("lineLaidOut(QQuickTextLine*)"); - return this->isSignalConnected(idx); -} - -void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height, qreal elideWidth = 0) -{ - Q_Q(QQuickText); - -#if defined(Q_OS_MAC) - if (QThread::currentThread() != paintingThread) { -#endif - if (!line.lineNumber()) - linesRects.clear(); - - if (!textLine) - textLine = new QQuickTextLine; - textLine->setLine(&line); - textLine->setY(height); - textLine->setHeight(0); - - // use the text item's width by default if it has one and wrap is on - if (q->widthValid() && q->wrapMode() != QQuickText::NoWrap) - textLine->setWidth(q->width() - elideWidth); - else - textLine->setWidth(INT_MAX); - if (lineHeight != 1.0) - textLine->setHeight((lineHeightMode == QQuickText::FixedHeight) ? lineHeight : line.height() * lineHeight); - - emit q->lineLaidOut(textLine); - - linesRects << QRectF(textLine->x(), textLine->y(), textLine->width(), textLine->height()); - height += textLine->height(); - -#if defined(Q_OS_MAC) - } else { - if (line.lineNumber() < linesRects.count()) { - QRectF r = linesRects.at(line.lineNumber()); - line.setLineWidth(r.width()); - line.setPosition(r.topLeft()); - } - } -#endif -} - -/*! - Lays out the QQuickTextPrivate::layout QTextLayout in the constraints of the QQuickText. - - Returns the size of the final text. This can be used to position the text vertically (the text is - already absolutely positioned horizontally). -*/ -QRect QQuickTextPrivate::setupTextLayout() -{ - // ### text layout handling should be profiled and optimized as needed - // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine); - Q_Q(QQuickText); - layout.setCacheEnabled(true); - - qreal lineWidth = 0; - int visibleCount = 0; - - //set manual width - if (q->widthValid()) - lineWidth = q->width(); - - QTextOption textOption = layout.textOption(); - textOption.setAlignment(Qt::Alignment(q->effectiveHAlign())); - textOption.setWrapMode(QTextOption::WrapMode(wrapMode)); - if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField()) - textOption.setUseDesignMetrics(true); - layout.setTextOption(textOption); - - QFontMetrics fm(layout.font()); - elidePos = QPointF(); - - if (requireImplicitWidth && q->widthValid()) { - // requires an extra layout - QString elidedText; - if (layoutTextElided) { - // We have provided elided text to the layout, but we must calculate unelided width. - elidedText = layout.text(); - layout.setText(text); - } - layout.beginLayout(); - forever { - QTextLine line = layout.createLine(); - if (!line.isValid()) - break; - } - layout.endLayout(); - QRectF br; - for (int i = 0; i < layout.lineCount(); ++i) { - QTextLine line = layout.lineAt(i); - br = br.united(line.naturalTextRect()); - } - naturalWidth = br.width(); - if (layoutTextElided) - layout.setText(elidedText); - } - - qreal height = 0; - QRectF br; - - bool truncate = false; - bool customLayout = isLineLaidOutConnected(); - bool elideEnabled = elideMode == QQuickText::ElideRight && q->widthValid(); - - layout.beginLayout(); - if (!lineWidth) - lineWidth = INT_MAX; - int linesLeft = maximumLineCount; - int visibleTextLength = 0; - forever { - QTextLine line = layout.createLine(); - if (!line.isValid()) - break; - - visibleCount++; - - qreal preLayoutHeight = height; - if (customLayout) { - setupCustomLineGeometry(line, height); - } else if (lineWidth) { - line.setLineWidth(lineWidth); - line.setPosition(QPointF(line.position().x(), height)); - height += (lineHeightMode == QQuickText::FixedHeight) ? lineHeight : line.height() * lineHeight; - } - - bool elide = false; - if (elideEnabled && q->heightValid() && height > q->height()) { - // This line does not fit in the remaining area. - elide = true; - if (visibleCount > 1) { - --visibleCount; - height = preLayoutHeight; - line.setLineWidth(0.0); - line.setPosition(QPointF(FLT_MAX,FLT_MAX)); - line = layout.lineAt(visibleCount-1); - } - } else { - visibleTextLength += line.textLength(); - } - - if (elide || (maximumLineCountValid && --linesLeft == 0)) { - if (visibleTextLength < text.length()) { - truncate = true; - if (elideEnabled) { - qreal elideWidth = fm.width(elideChar); - // Need to correct for alignment - if (customLayout) - setupCustomLineGeometry(line, height, elideWidth); - else - line.setLineWidth(lineWidth - elideWidth); - if (layout.text().mid(line.textStart(), line.textLength()).isRightToLeft()) { - line.setPosition(QPointF(line.position().x() + elideWidth, line.position().y())); - elidePos.setX(line.naturalTextRect().left() - elideWidth); - } else { - elidePos.setX(line.naturalTextRect().right()); - } - elidePos.setY(line.position().y()); - if (!elipsisLayout) - elipsisLayout = new QTextLayout(elideChar, layout.font()); - elipsisLayout->beginLayout(); - QTextLine el = elipsisLayout->createLine(); - el.setPosition(elidePos); - elipsisLayout->endLayout(); - br = br.united(el.naturalTextRect()); - } - br = br.united(line.naturalTextRect()); - break; - } - } - br = br.united(line.naturalTextRect()); - } - layout.endLayout(); - - //Update truncated - if (truncated != truncate) { - truncated = truncate; - emit q->truncatedChanged(); - } - - if (!customLayout) - br.setHeight(height); - - if (!q->widthValid()) - naturalWidth = br.width(); - - //Update the number of visible lines - if (lineCount != visibleCount) { - lineCount = visibleCount; - emit q->lineCountChanged(); - } - - return QRect(qRound(br.x()), qRound(br.y()), qCeil(br.width()), qCeil(br.height())); -} - -/*! - Returns a painted version of the QQuickTextPrivate::layout QTextLayout. - If \a drawStyle is true, the style color overrides all colors in the document. -*/ -QPixmap QQuickTextPrivate::textLayoutImage(bool drawStyle) -{ - QSize size = layedOutTextRect.size(); - - //paint text - QPixmap img(size); - if (!size.isEmpty()) { - img.fill(Qt::transparent); -/*#ifdef Q_OS_MAC // Fails on CocoaX64 - bool oldSmooth = qt_applefontsmoothing_enabled; - qt_applefontsmoothing_enabled = false; -#endif*/ - QPainter p(&img); -/*#ifdef Q_OS_MAC // Fails on CocoaX64 - qt_applefontsmoothing_enabled = oldSmooth; -#endif*/ - drawTextLayout(&p, QPointF(-layedOutTextRect.x(),0), drawStyle); - } - return img; -} - -/*! - Paints the QQuickTextPrivate::layout QTextLayout into \a painter at \a pos. If - \a drawStyle is true, the style color overrides all colors in the document. -*/ -void QQuickTextPrivate::drawTextLayout(QPainter *painter, const QPointF &pos, bool drawStyle) -{ - if (drawStyle) - painter->setPen(styleColor); - else - painter->setPen(color); - painter->setFont(font); - layout.draw(painter, pos); - if (!elidePos.isNull()) - painter->drawText(pos + elidePos, elideChar); -} - -/*! - Returns a painted version of the QQuickTextPrivate::doc QTextDocument. - If \a drawStyle is true, the style color overrides all colors in the document. -*/ -QPixmap QQuickTextPrivate::textDocumentImage(bool drawStyle) -{ - QSize size = doc->size().toSize(); - - //paint text - QPixmap img(size); - img.fill(Qt::transparent); -/*#ifdef Q_OS_MAC // Fails on CocoaX64 - bool oldSmooth = qt_applefontsmoothing_enabled; - qt_applefontsmoothing_enabled = false; -#endif*/ - QPainter p(&img); -/*#ifdef Q_OS_MAC // Fails on CocoaX64 - qt_applefontsmoothing_enabled = oldSmooth; -#endif*/ - - QAbstractTextDocumentLayout::PaintContext context; - - QTextOption oldOption(doc->defaultTextOption()); - if (drawStyle) { - context.palette.setColor(QPalette::Text, styleColor); - QTextOption colorOption(doc->defaultTextOption()); - colorOption.setFlags(QTextOption::SuppressColors); - doc->setDefaultTextOption(colorOption); - } else { - context.palette.setColor(QPalette::Text, color); - } - doc->documentLayout()->draw(&p, context); - if (drawStyle) - doc->setDefaultTextOption(oldOption); - return img; -} - -/*! - Mark the image cache as dirty. -*/ -void QQuickTextPrivate::invalidateImageCache() -{ - Q_Q(QQuickText); - - if (richTextAsImage || cacheAllTextAsImage || (qmlDisableDistanceField() && style != QQuickText::Normal)) { // If actually using the image cache - if (imageCacheDirty) - return; - - imageCacheDirty = true; - - if (q->isComponentComplete()) - QCoreApplication::postEvent(q, new QEvent(QEvent::User)); - } else if (q->isComponentComplete()) - q->update(); -} - -/*! - Tests if the image cache is dirty, and repaints it if it is. -*/ -void QQuickTextPrivate::checkImageCache() -{ - Q_Q(QQuickText); - - if (!imageCacheDirty) - return; - - if (text.isEmpty()) { - - imageCache = QPixmap(); - - } else { - - QPixmap textImage; - QPixmap styledImage; - - if (richText) { - textImage = textDocumentImage(false); - if (style != QQuickText::Normal) - styledImage = textDocumentImage(true); //### should use styleColor - } else { - textImage = textLayoutImage(false); - if (style != QQuickText::Normal) - styledImage = textLayoutImage(true); //### should use styleColor - } - - switch (style) { - case QQuickText::Outline: - imageCache = drawOutline(textImage, styledImage); - break; - case QQuickText::Sunken: - imageCache = drawOutline(textImage, styledImage, -1); - break; - case QQuickText::Raised: - imageCache = drawOutline(textImage, styledImage, 1); - break; - default: - imageCache = textImage; - break; - } - - } - - imageCacheDirty = false; - textureImageCacheDirty = true; - q->update(); -} - -/*! - Ensures the QQuickTextPrivate::doc variable is set to a valid text document -*/ -void QQuickTextPrivate::ensureDoc() -{ - if (!doc) { - Q_Q(QQuickText); - doc = new QQuickTextDocumentWithImageResources(q); - doc->setDocumentMargin(0); - } -} - -/*! - Draw \a styleSource as an outline around \a source and return the new image. -*/ -QPixmap QQuickTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource) -{ - QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2); - img.fill(Qt::transparent); - - QPainter ppm(&img); - - QPoint pos(0, 0); - pos += QPoint(-1, 0); - ppm.drawPixmap(pos, styleSource); - pos += QPoint(2, 0); - ppm.drawPixmap(pos, styleSource); - pos += QPoint(-1, -1); - ppm.drawPixmap(pos, styleSource); - pos += QPoint(0, 2); - ppm.drawPixmap(pos, styleSource); - - pos += QPoint(0, -1); - ppm.drawPixmap(pos, source); - ppm.end(); - - return img; -} - -/*! - Draw \a styleSource below \a source at \a yOffset and return the new image. -*/ -QPixmap QQuickTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset) -{ - QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2); - img.fill(Qt::transparent); - - QPainter ppm(&img); - - ppm.drawPixmap(QPoint(0, yOffset), styleSource); - ppm.drawPixmap(0, 0, source); - - ppm.end(); - - return img; -} - -/*! - \qmlclass Text QQuickText - \inqmlmodule QtQuick 2 - \ingroup qml-basic-visual-elements - \brief The Text item allows you to add formatted text to a scene. - \inherits Item - - Text items can display both plain and rich text. For example, red text with - a specific font and size can be defined like this: - - \qml - Text { - text: "Hello World!" - font.family: "Helvetica" - font.pointSize: 24 - color: "red" - } - \endqml - - Rich text is defined using HTML-style markup: - - \qml - Text { - text: "<b>Hello</b> <i>World!</i>" - } - \endqml - - \image declarative-text.png - - If height and width are not explicitly set, Text will attempt to determine how - much room is needed and set it accordingly. Unless \l wrapMode is set, it will always - prefer width to height (all text will be placed on a single line). - - The \l elide property can alternatively be used to fit a single line of - plain text to a set width. - - Note that the \l{Supported HTML Subset} is limited. Also, if the text contains - HTML img tags that load remote images, the text is reloaded. - - Text provides read-only text. For editable text, see \l TextEdit. - - \sa {declarative/text/fonts}{Fonts example} -*/ -QQuickText::QQuickText(QQuickItem *parent) -: QQuickImplicitSizeItem(*(new QQuickTextPrivate), parent) -{ - Q_D(QQuickText); - d->init(); -} - -QQuickText::~QQuickText() -{ -} - -/*! - \qmlproperty bool QtQuick2::Text::clip - This property holds whether the text is clipped. - - Note that if the text does not fit in the bounding rectangle it will be abruptly chopped. - - If you want to display potentially long text in a limited space, you probably want to use \c elide instead. -*/ - -/*! - \qmlproperty bool QtQuick2::Text::smooth - - This property holds whether the text is smoothly scaled or transformed. - - Smooth filtering gives better visual quality, but is slower. If - the item is displayed at its natural size, this property has no visual or - performance effect. - - \note Generally scaling artifacts are only visible if the item is stationary on - the screen. A common pattern when animating an item is to disable smooth - filtering at the beginning of the animation and reenable it at the conclusion. -*/ - -/*! - \qmlsignal QtQuick2::Text::onLineLaidOut(line) - - This handler is called for every line during the layout process. - This gives the opportunity to position and resize a line as it is being laid out. - It can for example be used to create columns or lay out text around objects. - - The properties of a line are: - \list - \o number (read-only) - \o x - \o y - \o width - \o height - \endlist - - For example, this will move the first 5 lines of a text element by 100 pixels to the right: - \code - onLineLaidOut: { - if (line.number < 5) { - line.x = line.x + 100 - line.width = line.width - 100 - } - } - \endcode -*/ - -/*! - \qmlsignal QtQuick2::Text::onLinkActivated(string link) - - This handler is called when the user clicks on a link embedded in the text. - The link must be in rich text or HTML format and the - \a link string provides access to the particular link. - - \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0 - - The example code will display the text - "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}." - - Clicking on the highlighted link will output - \tt{http://qt.nokia.com link activated} to the console. -*/ - -/*! - \qmlproperty string QtQuick2::Text::font.family - - Sets the family name of the font. - - The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]". - If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen. - If the family isn't available a family will be set using the font matching algorithm. -*/ - -/*! - \qmlproperty bool QtQuick2::Text::font.bold - - Sets whether the font weight is bold. -*/ - -/*! - \qmlproperty enumeration QtQuick2::Text::font.weight - - Sets the font's weight. - - The weight can be one of: - \list - \o Font.Light - \o Font.Normal - the default - \o Font.DemiBold - \o Font.Bold - \o Font.Black - \endlist - - \qml - Text { text: "Hello"; font.weight: Font.DemiBold } - \endqml -*/ - -/*! - \qmlproperty bool QtQuick2::Text::font.italic - - Sets whether the font has an italic style. -*/ - -/*! - \qmlproperty bool QtQuick2::Text::font.underline - - Sets whether the text is underlined. -*/ - -/*! - \qmlproperty bool QtQuick2::Text::font.strikeout - - Sets whether the font has a strikeout style. -*/ - -/*! - \qmlproperty real QtQuick2::Text::font.pointSize - - Sets the font size in points. The point size must be greater than zero. -*/ - -/*! - \qmlproperty int QtQuick2::Text::font.pixelSize - - Sets the font size in pixels. - - Using this function makes the font device dependent. - Use \c pointSize to set the size of the font in a device independent manner. -*/ - -/*! - \qmlproperty real QtQuick2::Text::font.letterSpacing - - Sets the letter spacing for the font. - - Letter spacing changes the default spacing between individual letters in the font. - A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing. -*/ - -/*! - \qmlproperty real QtQuick2::Text::font.wordSpacing - - Sets the word spacing for the font. - - Word spacing changes the default spacing between individual words. - A positive value increases the word spacing by a corresponding amount of pixels, - while a negative value decreases the inter-word spacing accordingly. -*/ - -/*! - \qmlproperty enumeration QtQuick2::Text::font.capitalization - - Sets the capitalization for the text. - - \list - \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied. - \o Font.AllUppercase - This alters the text to be rendered in all uppercase type. - \o Font.AllLowercase - This alters the text to be rendered in all lowercase type. - \o Font.SmallCaps - This alters the text to be rendered in small-caps type. - \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. - \endlist - - \qml - Text { text: "Hello"; font.capitalization: Font.AllLowercase } - \endqml -*/ -QFont QQuickText::font() const -{ - Q_D(const QQuickText); - return d->sourceFont; -} - -void QQuickText::setFont(const QFont &font) -{ - Q_D(QQuickText); - if (d->sourceFont == font) - return; - - d->sourceFont = font; - QFont oldFont = d->font; - d->font = font; - - if (d->font.pointSizeF() != -1) { - // 0.5pt resolution - qreal size = qRound(d->font.pointSizeF()*2.0); - d->font.setPointSizeF(size/2.0); - } - - if (oldFont != d->font) - d->updateLayout(); - - emit fontChanged(d->sourceFont); -} - -/*! - \qmlproperty string QtQuick2::Text::text - - The text to display. Text supports both plain and rich text strings. - - The item will try to automatically determine whether the text should - be treated as styled text. This determination is made using Qt::mightBeRichText(). -*/ -QString QQuickText::text() const -{ - Q_D(const QQuickText); - return d->text; -} - -void QQuickText::setText(const QString &n) -{ - Q_D(QQuickText); - if (d->text == n) - return; - - d->richText = d->format == RichText; - d->styledText = d->format == StyledText || (d->format == AutoText && Qt::mightBeRichText(n)); - d->text = n; - if (isComponentComplete()) { - if (d->richText) { - d->ensureDoc(); - d->doc->setText(n); - d->rightToLeftText = d->doc->toPlainText().isRightToLeft(); - d->richTextAsImage = enableImageCache(); - } else { - d->rightToLeftText = d->text.isRightToLeft(); - } - d->determineHorizontalAlignment(); - } - d->textHasChanged = true; - d->updateLayout(); - emit textChanged(d->text); -} - -/*! - \qmlproperty color QtQuick2::Text::color - - The text color. - - An example of green text defined using hexadecimal notation: - \qml - Text { - color: "#00FF00" - text: "green text" - } - \endqml - - An example of steel blue text defined using an SVG color name: - \qml - Text { - color: "steelblue" - text: "blue text" - } - \endqml -*/ -QColor QQuickText::color() const -{ - Q_D(const QQuickText); - return d->color; -} - -void QQuickText::setColor(const QColor &color) -{ - Q_D(QQuickText); - if (d->color == color) - return; - - d->color = color; - d->invalidateImageCache(); - emit colorChanged(d->color); -} -/*! - \qmlproperty enumeration QtQuick2::Text::style - - Set an additional text style. - - Supported text styles are: - \list - \o Text.Normal - the default - \o Text.Outline - \o Text.Raised - \o Text.Sunken - \endlist - - \qml - Row { - Text { font.pointSize: 24; text: "Normal" } - Text { font.pointSize: 24; text: "Raised"; style: Text.Raised; styleColor: "#AAAAAA" } - Text { font.pointSize: 24; text: "Outline";style: Text.Outline; styleColor: "red" } - Text { font.pointSize: 24; text: "Sunken"; style: Text.Sunken; styleColor: "#AAAAAA" } - } - \endqml - - \image declarative-textstyle.png -*/ -QQuickText::TextStyle QQuickText::style() const -{ - Q_D(const QQuickText); - return d->style; -} - -void QQuickText::setStyle(QQuickText::TextStyle style) -{ - Q_D(QQuickText); - if (d->style == style) - return; - - // changing to/from Normal requires the boundingRect() to change - if (isComponentComplete() && (d->style == Normal || style == Normal)) - update(); - d->style = style; - d->invalidateImageCache(); - emit styleChanged(d->style); -} - -/*! - \qmlproperty color QtQuick2::Text::styleColor - - Defines the secondary color used by text styles. - - \c styleColor is used as the outline color for outlined text, and as the - shadow color for raised or sunken text. If no style has been set, it is not - used at all. - - \qml - Text { font.pointSize: 18; text: "hello"; style: Text.Raised; styleColor: "gray" } - \endqml - - \sa style - */ -QColor QQuickText::styleColor() const -{ - Q_D(const QQuickText); - return d->styleColor; -} - -void QQuickText::setStyleColor(const QColor &color) -{ - Q_D(QQuickText); - if (d->styleColor == color) - return; - - d->styleColor = color; - d->invalidateImageCache(); - emit styleColorChanged(d->styleColor); -} - -/*! - \qmlproperty enumeration QtQuick2::Text::horizontalAlignment - \qmlproperty enumeration QtQuick2::Text::verticalAlignment - \qmlproperty enumeration QtQuick2::Text::effectiveHorizontalAlignment - - Sets the horizontal and vertical alignment of the text within the Text items - width and height. By default, the text is vertically aligned to the top. Horizontal - alignment follows the natural alignment of the text, for example text that is read - from left to right will be aligned to the left. - - The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight, \c Text.AlignHCenter and - \c Text.AlignJustify. The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom - and \c Text.AlignVCenter. - - Note that for a single line of text, the size of the text is the area of the text. In this common case, - all alignments are equivalent. If you want the text to be, say, centered in its parent, then you will - need to either modify the Item::anchors, or set horizontalAlignment to Text.AlignHCenter and bind the width to - that of the parent. - - When using the attached property LayoutMirroring::enabled to mirror application - layouts, the horizontal alignment of text will also be mirrored. However, the property - \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment - of Text, use the read-only property \c effectiveHorizontalAlignment. -*/ -QQuickText::HAlignment QQuickText::hAlign() const -{ - Q_D(const QQuickText); - return d->hAlign; -} - -void QQuickText::setHAlign(HAlignment align) -{ - Q_D(QQuickText); - bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror; - d->hAlignImplicit = false; - if (d->setHAlign(align, forceAlign) && isComponentComplete()) - d->updateLayout(); -} - -void QQuickText::resetHAlign() -{ - Q_D(QQuickText); - d->hAlignImplicit = true; - if (isComponentComplete() && d->determineHorizontalAlignment()) - d->updateLayout(); -} - -QQuickText::HAlignment QQuickText::effectiveHAlign() const -{ - Q_D(const QQuickText); - QQuickText::HAlignment effectiveAlignment = d->hAlign; - if (!d->hAlignImplicit && d->effectiveLayoutMirror) { - switch (d->hAlign) { - case QQuickText::AlignLeft: - effectiveAlignment = QQuickText::AlignRight; - break; - case QQuickText::AlignRight: - effectiveAlignment = QQuickText::AlignLeft; - break; - default: - break; - } - } - return effectiveAlignment; -} - -bool QQuickTextPrivate::setHAlign(QQuickText::HAlignment alignment, bool forceAlign) -{ - Q_Q(QQuickText); - if (hAlign != alignment || forceAlign) { - QQuickText::HAlignment oldEffectiveHAlign = q->effectiveHAlign(); - hAlign = alignment; - - emit q->horizontalAlignmentChanged(hAlign); - if (oldEffectiveHAlign != q->effectiveHAlign()) - emit q->effectiveHorizontalAlignmentChanged(); - return true; - } - return false; -} - -bool QQuickTextPrivate::determineHorizontalAlignment() -{ - if (hAlignImplicit) { - bool alignToRight = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : rightToLeftText; - return setHAlign(alignToRight ? QQuickText::AlignRight : QQuickText::AlignLeft); - } - return false; -} - -void QQuickTextPrivate::mirrorChange() -{ - Q_Q(QQuickText); - if (q->isComponentComplete()) { - if (!hAlignImplicit && (hAlign == QQuickText::AlignRight || hAlign == QQuickText::AlignLeft)) { - updateLayout(); - emit q->effectiveHorizontalAlignmentChanged(); - } - } -} - -QTextDocument *QQuickTextPrivate::textDocument() -{ - return doc; -} - -QQuickText::VAlignment QQuickText::vAlign() const -{ - Q_D(const QQuickText); - return d->vAlign; -} - -void QQuickText::setVAlign(VAlignment align) -{ - Q_D(QQuickText); - if (d->vAlign == align) - return; - - d->vAlign = align; - emit verticalAlignmentChanged(align); -} - -/*! - \qmlproperty enumeration QtQuick2::Text::wrapMode - - Set this property to wrap the text to the Text item's width. The text will only - wrap if an explicit width has been set. wrapMode can be one of: - - \list - \o Text.NoWrap (default) - no wrapping will be performed. If the text contains insufficient newlines, then \l paintedWidth will exceed a set width. - \o Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, \l paintedWidth will exceed a set width. - \o Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. - \o Text.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. - \endlist -*/ -QQuickText::WrapMode QQuickText::wrapMode() const -{ - Q_D(const QQuickText); - return d->wrapMode; -} - -void QQuickText::setWrapMode(WrapMode mode) -{ - Q_D(QQuickText); - if (mode == d->wrapMode) - return; - - d->wrapMode = mode; - d->updateLayout(); - - emit wrapModeChanged(); -} - -/*! - \qmlproperty int QtQuick2::Text::lineCount - - Returns the number of lines visible in the text item. - - This property is not supported for rich text. - - \sa maximumLineCount -*/ -int QQuickText::lineCount() const -{ - Q_D(const QQuickText); - return d->lineCount; -} - -/*! - \qmlproperty bool QtQuick2::Text::truncated - - Returns true if the text has been truncated due to \l maximumLineCount - or \l elide. - - This property is not supported for rich text. - - \sa maximumLineCount, elide -*/ -bool QQuickText::truncated() const -{ - Q_D(const QQuickText); - return d->truncated; -} - -/*! - \qmlproperty int QtQuick2::Text::maximumLineCount - - Set this property to limit the number of lines that the text item will show. - If elide is set to Text.ElideRight, the text will be elided appropriately. - By default, this is the value of the largest possible integer. - - This property is not supported for rich text. - - \sa lineCount, elide -*/ -int QQuickText::maximumLineCount() const -{ - Q_D(const QQuickText); - return d->maximumLineCount; -} - -void QQuickText::setMaximumLineCount(int lines) -{ - Q_D(QQuickText); - - d->maximumLineCountValid = lines==INT_MAX ? false : true; - if (d->maximumLineCount != lines) { - d->maximumLineCount = lines; - d->updateLayout(); - emit maximumLineCountChanged(); - } -} - -void QQuickText::resetMaximumLineCount() -{ - Q_D(QQuickText); - setMaximumLineCount(INT_MAX); - d->elidePos = QPointF(); - if (d->truncated != false) { - d->truncated = false; - emit truncatedChanged(); - } -} - -/*! - \qmlproperty enumeration QtQuick2::Text::textFormat - - The way the text property should be displayed. - - Supported text formats are: - - \list - \o Text.AutoText (default) - \o Text.PlainText - \o Text.StyledText - \o Text.RichText - \endlist - - If the text format is \c Text.AutoText the text element - will automatically determine whether the text should be treated as - styled text. This determination is made using Qt::mightBeRichText(). - - Text.StyledText is an optimized format supporting some basic text - styling markup, in the style of html 3.2: - - \code - <b></b> - bold - <i></i> - italic - <br> - new line - <p> - paragraph - <u> - underlined text - <font color="color_name" size="1-7"></font> - <h1> to <h6> - headers - <a href=""> - anchor - <ol type="">, <ul type=""> and <li> - ordered and unordered lists - > < & - \endcode - - \c Text.StyledText parser is strict, requiring tags to be correctly nested. - - \table - \row - \o - \qml -Column { - Text { - font.pointSize: 24 - text: "<b>Hello</b> <i>World!</i>" - } - Text { - font.pointSize: 24 - textFormat: Text.RichText - text: "<b>Hello</b> <i>World!</i>" - } - Text { - font.pointSize: 24 - textFormat: Text.PlainText - text: "<b>Hello</b> <i>World!</i>" - } -} - \endqml - \o \image declarative-textformat.png - \endtable -*/ -QQuickText::TextFormat QQuickText::textFormat() const -{ - Q_D(const QQuickText); - return d->format; -} - -void QQuickText::setTextFormat(TextFormat format) -{ - Q_D(QQuickText); - if (format == d->format) - return; - d->format = format; - bool wasRich = d->richText; - d->richText = format == RichText; - d->styledText = format == StyledText || (format == AutoText && Qt::mightBeRichText(d->text)); - - if (isComponentComplete()) { - if (!wasRich && d->richText) { - d->ensureDoc(); - d->doc->setText(d->text); - d->rightToLeftText = d->doc->toPlainText().isRightToLeft(); - d->richTextAsImage = enableImageCache(); - } else { - d->rightToLeftText = d->text.isRightToLeft(); - } - d->determineHorizontalAlignment(); - } - d->updateLayout(); - - emit textFormatChanged(d->format); -} - -/*! - \qmlproperty enumeration QtQuick2::Text::elide - - Set this property to elide parts of the text fit to the Text item's width. - The text will only elide if an explicit width has been set. - - This property cannot be used with rich text. - - Eliding can be: - \list - \o Text.ElideNone - the default - \o Text.ElideLeft - \o Text.ElideMiddle - \o Text.ElideRight - \endlist - - If this property is set to Text.ElideRight, it can be used with multiline - text. The text will only elide if \c maximumLineCount, or \c height has been set. - If both \c maximumLineCount and \c height are set, \c maximumLineCount will - apply unless the lines do not fit in the height allowed. - - If the text is a multi-length string, and the mode is not \c Text.ElideNone, - the first string that fits will be used, otherwise the last will be elided. - - Multi-length strings are ordered from longest to shortest, separated by the - Unicode "String Terminator" character \c U009C (write this in QML with \c{"\u009C"} or \c{"\x9C"}). -*/ -QQuickText::TextElideMode QQuickText::elideMode() const -{ - Q_D(const QQuickText); - return d->elideMode; -} - -void QQuickText::setElideMode(QQuickText::TextElideMode mode) -{ - Q_D(QQuickText); - if (mode == d->elideMode) - return; - - d->elideMode = mode; - d->updateLayout(); - - emit elideModeChanged(d->elideMode); -} - -/*! \internal */ -QRectF QQuickText::boundingRect() const -{ - Q_D(const QQuickText); - - QRect rect = d->layedOutTextRect; - if (d->style != Normal) - rect.adjust(-1, 0, 1, 2); - - // Could include font max left/right bearings to either side of rectangle. - - int h = height(); - switch (d->vAlign) { - case AlignTop: - break; - case AlignBottom: - rect.moveTop(h - rect.height()); - break; - case AlignVCenter: - rect.moveTop((h - rect.height()) / 2); - break; - } - - return QRectF(rect); -} - -/*! \internal */ -void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) -{ - Q_D(QQuickText); - bool elide = d->elideMode != QQuickText::ElideNone && widthValid(); - if ((!d->internalWidthUpdate - && (newGeometry.width() != oldGeometry.width() || (elide && newGeometry.height() != oldGeometry.height()))) - && (d->wrapMode != QQuickText::NoWrap - || d->elideMode != QQuickText::ElideNone - || d->hAlign != QQuickText::AlignLeft)) { - if ((d->singleline || d->maximumLineCountValid || heightValid()) && elide) { - // We need to re-elide - d->updateLayout(); - } else { - // We just need to re-layout - d->updateSize(); - } - } - - QQuickItem::geometryChanged(newGeometry, oldGeometry); -} - -QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) -{ - Q_UNUSED(data); - Q_D(QQuickText); - - if (d->text.isEmpty()) { - delete oldNode; - return 0; - } - - QRectF bounds = boundingRect(); - - // We need to make sure the layout is done in the current thread -#if defined(Q_OS_MAC) - d->paintingThread = QThread::currentThread(); - if (d->layoutThread != d->paintingThread) - d->updateLayout(); -#endif - - // XXX todo - some styled text can be done by the QQuickTextNode - if (d->richTextAsImage || d->cacheAllTextAsImage || (qmlDisableDistanceField() && d->style != Normal)) { - bool wasDirty = d->textureImageCacheDirty; - d->textureImageCacheDirty = false; - - if (d->imageCache.isNull()) { - delete oldNode; - return 0; - } - - QSGImageNode *node = 0; - if (!oldNode || d->nodeType != QQuickTextPrivate::NodeIsTexture) { - delete oldNode; - node = QQuickItemPrivate::get(this)->sceneGraphContext()->createImageNode(); - d->texture = new QSGPlainTexture(); - wasDirty = true; - d->nodeType = QQuickTextPrivate::NodeIsTexture; - } else { - node = static_cast<QSGImageNode *>(oldNode); - Q_ASSERT(d->texture); - } - - if (wasDirty) { - qobject_cast<QSGPlainTexture *>(d->texture)->setImage(d->imageCache.toImage()); - node->setTexture(0); - node->setTexture(d->texture); - } - - node->setTargetRect(QRectF(bounds.x(), bounds.y(), d->imageCache.width(), d->imageCache.height())); - node->setSourceRect(QRectF(0, 0, 1, 1)); - node->setHorizontalWrapMode(QSGTexture::ClampToEdge); - node->setVerticalWrapMode(QSGTexture::ClampToEdge); - node->setFiltering(QSGTexture::Linear); // Nonsmooth text just ugly, so don't do that.. - node->update(); - - return node; - - } else { - QQuickTextNode *node = 0; - if (!oldNode || d->nodeType != QQuickTextPrivate::NodeIsText) { - delete oldNode; - node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext()); - d->nodeType = QQuickTextPrivate::NodeIsText; - } else { - node = static_cast<QQuickTextNode *>(oldNode); - } - - node->deleteContent(); - node->setMatrix(QMatrix4x4()); - - if (d->richText) { - d->ensureDoc(); - node->addTextDocument(bounds.topLeft(), d->doc, d->color, d->style, d->styleColor); - - } else { - node->addTextLayout(QPoint(0, bounds.y()), &d->layout, d->color, d->style, d->styleColor); - if (d->elipsisLayout) - node->addTextLayout(QPoint(0, bounds.y()), d->elipsisLayout, d->color, d->style, d->styleColor); - } - - return node; - } -} - -bool QQuickText::event(QEvent *e) -{ - Q_D(QQuickText); - if (e->type() == QEvent::User) { - d->checkImageCache(); - return true; - } else { - return QQuickImplicitSizeItem::event(e); - } -} - -/*! - \qmlproperty real QtQuick2::Text::paintedWidth - - Returns the width of the text, including width past the width - which is covered due to insufficient wrapping if WrapMode is set. -*/ -qreal QQuickText::paintedWidth() const -{ - Q_D(const QQuickText); - return d->paintedSize.width(); -} - -/*! - \qmlproperty real QtQuick2::Text::paintedHeight - - Returns the height of the text, including height past the height - which is covered due to there being more text than fits in the set height. -*/ -qreal QQuickText::paintedHeight() const -{ - Q_D(const QQuickText); - return d->paintedSize.height(); -} - -/*! - \qmlproperty real QtQuick2::Text::lineHeight - - Sets the line height for the text. - The value can be in pixels or a multiplier depending on lineHeightMode. - - The default value is a multiplier of 1.0. - The line height must be a positive value. -*/ -qreal QQuickText::lineHeight() const -{ - Q_D(const QQuickText); - return d->lineHeight; -} - -void QQuickText::setLineHeight(qreal lineHeight) -{ - Q_D(QQuickText); - - if ((d->lineHeight == lineHeight) || (lineHeight < 0.0)) - return; - - d->lineHeight = lineHeight; - d->updateLayout(); - emit lineHeightChanged(lineHeight); -} - -/*! - \qmlproperty enumeration QtQuick2::Text::lineHeightMode - - This property determines how the line height is specified. - The possible values are: - - \list - \o Text.ProportionalHeight (default) - this sets the spacing proportional to the - line (as a multiplier). For example, set to 2 for double spacing. - \o Text.FixedHeight - this sets the line height to a fixed line height (in pixels). - \endlist -*/ -QQuickText::LineHeightMode QQuickText::lineHeightMode() const -{ - Q_D(const QQuickText); - return d->lineHeightMode; -} - -void QQuickText::setLineHeightMode(LineHeightMode mode) -{ - Q_D(QQuickText); - if (mode == d->lineHeightMode) - return; - - d->lineHeightMode = mode; - d->updateLayout(); - - emit lineHeightModeChanged(mode); -} - -/*! - Returns the number of resources (images) that are being loaded asynchronously. -*/ -int QQuickText::resourcesLoading() const -{ - Q_D(const QQuickText); - return d->doc ? d->doc->resourcesLoading() : 0; -} - -/*! \internal */ -void QQuickText::componentComplete() -{ - Q_D(QQuickText); - if (d->updateOnComponentComplete) { - if (d->richText) { - d->ensureDoc(); - d->doc->setText(d->text); - d->rightToLeftText = d->doc->toPlainText().isRightToLeft(); - d->richTextAsImage = enableImageCache(); - } else { - d->rightToLeftText = d->text.isRightToLeft(); - } - d->determineHorizontalAlignment(); - } - QQuickItem::componentComplete(); - if (d->updateOnComponentComplete) - d->updateLayout(); -} - - -QString QQuickTextPrivate::anchorAt(const QPointF &mousePos) -{ - if (styledText) { - for (int i = 0; i < layout.lineCount(); ++i) { - QTextLine line = layout.lineAt(i); - if (line.naturalTextRect().contains(mousePos)) { - int charPos = line.xToCursor(mousePos.x()); - foreach (const QTextLayout::FormatRange &formatRange, layout.additionalFormats()) { - if (formatRange.format.isAnchor() - && charPos >= formatRange.start - && charPos <= formatRange.start + formatRange.length) { - return formatRange.format.anchorHref(); - } - } - break; - } - } - } - return QString(); -} - -bool QQuickTextPrivate::isLinkActivatedConnected() -{ - static int idx = this->signalIndex("linkActivated(QString)"); - return this->isSignalConnected(idx); -} - -/*! \internal */ -void QQuickText::mousePressEvent(QMouseEvent *event) -{ - Q_D(QQuickText); - - if (d->isLinkActivatedConnected()) { - if (d->styledText) - d->activeLink = d->anchorAt(event->localPos()); - else if (d->richText && d->doc) - d->activeLink = d->doc->documentLayout()->anchorAt(event->localPos()); - } - - if (d->activeLink.isEmpty()) - event->setAccepted(false); - - // ### may malfunction if two of the same links are clicked & dragged onto each other) - - if (!event->isAccepted()) - QQuickItem::mousePressEvent(event); - -} - -/*! \internal */ -void QQuickText::mouseReleaseEvent(QMouseEvent *event) -{ - Q_D(QQuickText); - - // ### confirm the link, and send a signal out - - QString link; - if (d->isLinkActivatedConnected()) { - if (d->styledText) - link = d->anchorAt(event->localPos()); - else if (d->richText && d->doc) - link = d->doc->documentLayout()->anchorAt(event->localPos()); - } - - if (!link.isEmpty() && d->activeLink == link) - emit linkActivated(d->activeLink); - else - event->setAccepted(false); - - if (!event->isAccepted()) - QQuickItem::mouseReleaseEvent(event); -} - -QT_END_NAMESPACE - -#include "qquicktext.moc" |