~ubuntu-branches/ubuntu/precise/qt4-x11/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/a11y_qt_and_qml_backport.diff/src/declarative/graphicsitems/qdeclarativetext.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell, Jonathan Riddell, Felix Geyer
  • Date: 2011-11-01 16:23:55 UTC
  • mfrom: (15.3.22 sid)
  • Revision ID: package-import@ubuntu.com-20111101162355-4dhsj6563ii8enl6
Tags: 4:4.7.4-1ubuntu1
[ Jonathan Riddell ]
* Merge from Debian Git packaging.  Remaining Ubuntu changes:
  - Do not package ibase/firebird package, remove from debian/rules and
    debian/control
  - libqt4-sql-ibase not recommend for libqt4-sql
  - build with -no-phonon
  - do not build libqt4-phonon, disable in debian/control
  - Build packages with lzma compression using the dh addon from pkg-kde-tools
  - Rules to remove po dir in clean
  - Add MessagesQt.sh
  - Rules to create Messages.sh link to MessagesQt.sh and rules to create po
    dir and exectue extract-messages.sh in common-install-prehook-impl
  - Make libqt4-dev depend on libx11-dev
  - Add and install Trolltech.conf in libqtcore4.install
  - Build QtWebkit and use it only for QtAssistant
    + Rule to put qt_webkit_version.pri in mkspecs/modules
    + Rule to remove libQtWebKit* after build
    + Exclude usr/bin/assistant-qt4 from dh_shlibdeps
  - Fix Lucid upgrades: libqt4-help breaks/replaces libqtcore4 (<< 4:4.7.0)
  - Change OpenGL backend from GL to GLES 2 for armel (Debian does this for
    armhf)
    + Build-depend and make libqt4-opengl-dev depend on libgles2-mesa-dev
      instead of libgl1-mesa-dev and libglu1-mesa-dev
    + Pass "-opengl es2" to configure
  - Pass extra_configure_opts += -arch armv6 on both armel and armhf and not
    just armhf
  - In debian/rules Move documentation building to override_dh_auto_install where
    dh_listpackages works as expected with dpkg-buildpackage. (LP: #857377)
  - debian/compat is 9 and build-depend on newer debhelper for multiarch
* debian/patches/blacklist-diginotar-certs.diff is now
  debian/patches/blacklist-diginotar-cert.diff to match Debian
* Add prefix to some patches to clarify they come from Ubuntu rather than Debian
 - kubuntu_97_a11y_qt_and_qml_backport.diff
 - kubuntu_98_fix_accessible_menu.diff
 - kubuntu_99_notify_qml_name_description_change.diff

[ Felix Geyer ]
* Use DEB_*_MAINT_APPEND instead of setting CXXFLAGS and LDFLAGS.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/****************************************************************************
2
 
**
3
 
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
 
** All rights reserved.
5
 
** Contact: Nokia Corporation (qt-info@nokia.com)
6
 
**
7
 
** This file is part of the QtDeclarative module of the Qt Toolkit.
8
 
**
9
 
** $QT_BEGIN_LICENSE:LGPL$
10
 
** GNU Lesser General Public License Usage
11
 
** This file may be used under the terms of the GNU Lesser General Public
12
 
** License version 2.1 as published by the Free Software Foundation and
13
 
** appearing in the file LICENSE.LGPL included in the packaging of this
14
 
** file. Please review the following information to ensure the GNU Lesser
15
 
** General Public License version 2.1 requirements will be met:
16
 
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
 
**
18
 
** In addition, as a special exception, Nokia gives you certain additional
19
 
** rights. These rights are described in the Nokia Qt LGPL Exception
20
 
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
 
**
22
 
** GNU General Public License Usage
23
 
** Alternatively, this file may be used under the terms of the GNU General
24
 
** Public License version 3.0 as published by the Free Software Foundation
25
 
** and appearing in the file LICENSE.GPL included in the packaging of this
26
 
** file. Please review the following information to ensure the GNU General
27
 
** Public License version 3.0 requirements will be met:
28
 
** http://www.gnu.org/copyleft/gpl.html.
29
 
**
30
 
** Other Usage
31
 
** Alternatively, this file may be used in accordance with the terms and
32
 
** conditions contained in a signed written agreement between you and Nokia.
33
 
**
34
 
**
35
 
**
36
 
**
37
 
**
38
 
** $QT_END_LICENSE$
39
 
**
40
 
****************************************************************************/
41
 
 
42
 
#include "private/qdeclarativetext_p.h"
43
 
#include "private/qdeclarativetext_p_p.h"
44
 
#include <private/qtextdocumentlayout_p.h>
45
 
#include <qdeclarativestyledtext_p.h>
46
 
#include <qdeclarativeinfo.h>
47
 
#include <qdeclarativepixmapcache_p.h>
48
 
 
49
 
#include <QSet>
50
 
#include <QTextLayout>
51
 
#include <QTextLine>
52
 
#include <QTextDocument>
53
 
#include <QGraphicsSceneMouseEvent>
54
 
#include <QPainter>
55
 
#include <QAbstractTextDocumentLayout>
56
 
#include <qmath.h>
57
 
#include <limits.h>
58
 
 
59
 
QT_BEGIN_NAMESPACE
60
 
 
61
 
extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
62
 
 
63
 
class QTextDocumentWithImageResources : public QTextDocument {
64
 
    Q_OBJECT
65
 
 
66
 
public:
67
 
    QTextDocumentWithImageResources(QDeclarativeText *parent);
68
 
    virtual ~QTextDocumentWithImageResources();
69
 
 
70
 
    void setText(const QString &);
71
 
    int resourcesLoading() const { return outstanding; }
72
 
 
73
 
protected:
74
 
    QVariant loadResource(int type, const QUrl &name);
75
 
 
76
 
private slots:
77
 
    void requestFinished();
78
 
 
79
 
private:
80
 
    QHash<QUrl, QDeclarativePixmap *> m_resources;
81
 
 
82
 
    int outstanding;
83
 
    static QSet<QUrl> errors;
84
 
};
85
 
 
86
 
class QDeclarativeTextDocumentLayout : public QTextDocumentLayout
87
 
{
88
 
    Q_OBJECT
89
 
public:
90
 
    QDeclarativeTextDocumentLayout(QTextDocument *doc);
91
 
    void setLineHeight(qreal lineHeight, QDeclarativeText::LineHeightMode mode);
92
 
};
93
 
 
94
 
DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE);
95
 
 
96
 
QString QDeclarativeTextPrivate::elideChar = QString(0x2026);
97
 
 
98
 
QDeclarativeTextPrivate::QDeclarativeTextPrivate()
99
 
: color((QRgb)0), style(QDeclarativeText::Normal), hAlign(QDeclarativeText::AlignLeft),
100
 
  vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone),
101
 
  format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineHeight(1),
102
 
  lineHeightMode(QDeclarativeText::ProportionalHeight), lineCount(1), truncated(false), maximumLineCount(INT_MAX),
103
 
  maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false),
104
 
  cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false),  hAlignImplicit(true),
105
 
  rightToLeftText(false), layoutTextElided(false), naturalWidth(0), doc(0)
106
 
{
107
 
    cacheAllTextAsImage = enableImageCache();
108
 
    QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton;
109
 
    QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents;
110
 
}
111
 
 
112
 
QTextDocumentWithImageResources::QTextDocumentWithImageResources(QDeclarativeText *parent) 
113
 
: QTextDocument(parent), outstanding(0)
114
 
{
115
 
}
116
 
 
117
 
QTextDocumentWithImageResources::~QTextDocumentWithImageResources()
118
 
{
119
 
    if (!m_resources.isEmpty()) 
120
 
        qDeleteAll(m_resources);
121
 
}
122
 
 
123
 
QVariant QTextDocumentWithImageResources::loadResource(int type, const QUrl &name)
124
 
{
125
 
    QDeclarativeContext *context = qmlContext(parent());
126
 
    QUrl url = context->resolvedUrl(name);
127
 
 
128
 
    if (type == QTextDocument::ImageResource) {
129
 
        QHash<QUrl, QDeclarativePixmap *>::Iterator iter = m_resources.find(url);
130
 
 
131
 
        if (iter == m_resources.end()) {
132
 
            QDeclarativePixmap *p = new QDeclarativePixmap(context->engine(), url);
133
 
            iter = m_resources.insert(name, p);
134
 
 
135
 
            if (p->isLoading()) {
136
 
                p->connectFinished(this, SLOT(requestFinished()));
137
 
                outstanding++;
138
 
            }
139
 
        }
140
 
 
141
 
        QDeclarativePixmap *p = *iter;
142
 
        if (p->isReady()) {
143
 
            return p->pixmap();
144
 
        } else if (p->isError()) {
145
 
            if (!errors.contains(url)) {
146
 
                errors.insert(url);
147
 
                qmlInfo(parent()) << p->error();
148
 
            }
149
 
        }
150
 
    }
151
 
 
152
 
    return QTextDocument::loadResource(type,url); // The *resolved* URL
153
 
}
154
 
 
155
 
void QTextDocumentWithImageResources::requestFinished()
156
 
{
157
 
    outstanding--;
158
 
    if (outstanding == 0) {
159
 
        QDeclarativeText *textItem = static_cast<QDeclarativeText*>(parent());
160
 
        QString text = textItem->text();
161
 
#ifndef QT_NO_TEXTHTMLPARSER
162
 
        setHtml(text);
163
 
#else
164
 
        setPlainText(text);
165
 
#endif
166
 
        QDeclarativeTextPrivate *d = QDeclarativeTextPrivate::get(textItem);
167
 
        d->updateLayout();
168
 
    }
169
 
}
170
 
 
171
 
void QTextDocumentWithImageResources::setText(const QString &text)
172
 
{
173
 
    if (!m_resources.isEmpty()) {
174
 
        qDeleteAll(m_resources);
175
 
        m_resources.clear();
176
 
        outstanding = 0;
177
 
    }
178
 
 
179
 
#ifndef QT_NO_TEXTHTMLPARSER
180
 
    setHtml(text);
181
 
#else
182
 
    setPlainText(text);
183
 
#endif
184
 
}
185
 
 
186
 
QSet<QUrl> QTextDocumentWithImageResources::errors;
187
 
 
188
 
QDeclarativeTextDocumentLayout::QDeclarativeTextDocumentLayout(QTextDocument *doc)
189
 
    : QTextDocumentLayout(doc) {
190
 
}
191
 
 
192
 
void QDeclarativeTextDocumentLayout::setLineHeight(qreal lineHeight, QDeclarativeText::LineHeightMode mode = QDeclarativeText::ProportionalHeight)
193
 
{
194
 
    QTextDocumentLayout::setLineHeight(lineHeight, QTextDocumentLayout::LineHeightMode(mode));
195
 
}
196
 
 
197
 
QDeclarativeTextPrivate::~QDeclarativeTextPrivate()
198
 
{
199
 
}
200
 
 
201
 
qreal QDeclarativeTextPrivate::implicitWidth() const
202
 
{
203
 
    if (!requireImplicitWidth) {
204
 
        // We don't calculate implicitWidth unless it is required.
205
 
        // We need to force a size update now to ensure implicitWidth is calculated
206
 
        QDeclarativeTextPrivate *me = const_cast<QDeclarativeTextPrivate*>(this);
207
 
        me->requireImplicitWidth = true;
208
 
        me->updateSize();
209
 
    }
210
 
    return mImplicitWidth;
211
 
}
212
 
 
213
 
void QDeclarativeTextPrivate::updateLayout()
214
 
{
215
 
    Q_Q(QDeclarativeText);
216
 
    if (!q->isComponentComplete()) {
217
 
        updateOnComponentComplete = true;
218
 
        return;
219
 
    }
220
 
 
221
 
    layoutTextElided = false;
222
 
    // Setup instance of QTextLayout for all cases other than richtext
223
 
    if (!richText) {
224
 
        layout.clearLayout();
225
 
        layout.setFont(font);
226
 
        if (format != QDeclarativeText::StyledText) {
227
 
            QString tmp = text;
228
 
            tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
229
 
            singleline = !tmp.contains(QChar::LineSeparator);
230
 
            if (singleline && !maximumLineCountValid && elideMode != QDeclarativeText::ElideNone && q->widthValid()) {
231
 
                QFontMetrics fm(font);
232
 
                tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width());
233
 
                if (tmp != text) {
234
 
                    layoutTextElided = true;
235
 
                    if (!truncated) {
236
 
                        truncated = true;
237
 
                        emit q->truncatedChanged();
238
 
                    }
239
 
                }
240
 
            }
241
 
            layout.setText(tmp);
242
 
        } else {
243
 
            singleline = false;
244
 
            QDeclarativeStyledText::parse(text, layout);
245
 
        }
246
 
    } else {
247
 
        ensureDoc();
248
 
        QDeclarativeTextDocumentLayout *layout = new QDeclarativeTextDocumentLayout(doc);
249
 
        layout->setLineHeight(lineHeight, lineHeightMode);
250
 
        doc->setDocumentLayout(layout);
251
 
    }
252
 
 
253
 
    updateSize();
254
 
}
255
 
 
256
 
void QDeclarativeTextPrivate::updateSize()
257
 
{
258
 
    Q_Q(QDeclarativeText);
259
 
 
260
 
    if (!q->isComponentComplete()) {
261
 
        updateOnComponentComplete = true;
262
 
        return;
263
 
    }
264
 
 
265
 
    if (!requireImplicitWidth) {
266
 
        emit q->implicitWidthChanged();
267
 
        // if the implicitWidth is used, then updateSize() has already been called (recursively)
268
 
        if (requireImplicitWidth)
269
 
            return;
270
 
    }
271
 
 
272
 
    invalidateImageCache();
273
 
 
274
 
    QFontMetrics fm(font);
275
 
    if (text.isEmpty()) {
276
 
        q->setImplicitWidth(0);
277
 
        q->setImplicitHeight(fm.height());
278
 
        paintedSize = QSize(0, fm.height());
279
 
        emit q->paintedSizeChanged();
280
 
        q->update();
281
 
        return;
282
 
    }
283
 
 
284
 
    int dy = q->height();
285
 
    QSize size(0, 0);
286
 
 
287
 
    //setup instance of QTextLayout for all cases other than richtext
288
 
    if (!richText) {
289
 
        QRect textRect = setupTextLayout();
290
 
        if (layedOutTextRect.size() != textRect.size())
291
 
            q->prepareGeometryChange();
292
 
        layedOutTextRect = textRect;
293
 
        size = textRect.size();
294
 
        dy -= size.height();
295
 
    } else {
296
 
        singleline = false; // richtext can't elide or be optimized for single-line case
297
 
        ensureDoc();
298
 
        doc->setDefaultFont(font);
299
 
 
300
 
        QDeclarativeText::HAlignment horizontalAlignment = q->effectiveHAlign();
301
 
        if (rightToLeftText) {
302
 
            if (horizontalAlignment == QDeclarativeText::AlignLeft)
303
 
                horizontalAlignment = QDeclarativeText::AlignRight;
304
 
            else if (horizontalAlignment == QDeclarativeText::AlignRight)
305
 
                horizontalAlignment = QDeclarativeText::AlignLeft;
306
 
        }
307
 
        QTextOption option;
308
 
        option.setAlignment((Qt::Alignment)int(horizontalAlignment | vAlign));
309
 
        option.setWrapMode(QTextOption::WrapMode(wrapMode));
310
 
        doc->setDefaultTextOption(option);
311
 
        if (requireImplicitWidth && q->widthValid()) {
312
 
            doc->setTextWidth(-1);
313
 
            naturalWidth = doc->idealWidth();
314
 
        }
315
 
        if (wrapMode != QDeclarativeText::NoWrap && q->widthValid())
316
 
            doc->setTextWidth(q->width());
317
 
        else
318
 
            doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
319
 
        dy -= (int)doc->size().height();
320
 
        QSize dsize = doc->size().toSize();
321
 
        if (dsize != layedOutTextRect.size()) {
322
 
            q->prepareGeometryChange();
323
 
            layedOutTextRect = QRect(QPoint(0,0), dsize);
324
 
        }
325
 
        size = QSize(int(doc->idealWidth()),dsize.height());
326
 
    }
327
 
    int yoff = 0;
328
 
 
329
 
    if (q->heightValid()) {
330
 
        if (vAlign == QDeclarativeText::AlignBottom)
331
 
            yoff = dy;
332
 
        else if (vAlign == QDeclarativeText::AlignVCenter)
333
 
            yoff = dy/2;
334
 
    }
335
 
    q->setBaselineOffset(fm.ascent() + yoff);
336
 
 
337
 
    //### need to comfirm cost of always setting these for richText
338
 
    internalWidthUpdate = true;
339
 
    if (!q->widthValid())
340
 
        q->setImplicitWidth(size.width());
341
 
    else if (requireImplicitWidth)
342
 
        q->setImplicitWidth(naturalWidth);
343
 
    internalWidthUpdate = false;
344
 
    q->setImplicitHeight(size.height());
345
 
    if (paintedSize != size) {
346
 
        paintedSize = size;
347
 
        emit q->paintedSizeChanged();
348
 
    }
349
 
    q->update();
350
 
}
351
 
 
352
 
/*!
353
 
    Lays out the QDeclarativeTextPrivate::layout QTextLayout in the constraints of the QDeclarativeText.
354
 
 
355
 
    Returns the size of the final text.  This can be used to position the text vertically (the text is
356
 
    already absolutely positioned horizontally).
357
 
*/
358
 
QRect QDeclarativeTextPrivate::setupTextLayout()
359
 
{
360
 
    // ### text layout handling should be profiled and optimized as needed
361
 
    // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
362
 
    Q_Q(QDeclarativeText);
363
 
    layout.setCacheEnabled(true);
364
 
 
365
 
    qreal lineWidth = 0;
366
 
    int visibleCount = 0;
367
 
 
368
 
    //set manual width
369
 
    if (q->widthValid())
370
 
        lineWidth = q->width();
371
 
 
372
 
    QTextOption textOption = layout.textOption();
373
 
    textOption.setAlignment(Qt::Alignment(q->effectiveHAlign()));
374
 
    textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
375
 
    layout.setTextOption(textOption);
376
 
 
377
 
    bool elideText = false;
378
 
    bool truncate = false;
379
 
 
380
 
    QFontMetrics fm(layout.font());
381
 
    elidePos = QPointF();
382
 
 
383
 
    if (requireImplicitWidth && q->widthValid()) {
384
 
        // requires an extra layout
385
 
        QString elidedText;
386
 
        if (layoutTextElided) {
387
 
            // We have provided elided text to the layout, but we must calculate unelided width.
388
 
            elidedText = layout.text();
389
 
            layout.setText(text);
390
 
        }
391
 
        layout.beginLayout();
392
 
        forever {
393
 
            QTextLine line = layout.createLine();
394
 
            if (!line.isValid())
395
 
                break;
396
 
        }
397
 
        layout.endLayout();
398
 
        QRectF br;
399
 
        for (int i = 0; i < layout.lineCount(); ++i) {
400
 
            QTextLine line = layout.lineAt(i);
401
 
            br = br.united(line.naturalTextRect());
402
 
        }
403
 
        naturalWidth = br.width();
404
 
        if (layoutTextElided)
405
 
            layout.setText(elidedText);
406
 
    }
407
 
 
408
 
    if (maximumLineCountValid) {
409
 
        layout.beginLayout();
410
 
        if (!lineWidth)
411
 
            lineWidth = INT_MAX;
412
 
        int linesLeft = maximumLineCount;
413
 
        int visibleTextLength = 0;
414
 
        while (linesLeft > 0) {
415
 
            QTextLine line = layout.createLine();
416
 
            if (!line.isValid())
417
 
                break;
418
 
 
419
 
            visibleCount++;
420
 
            if (lineWidth)
421
 
                line.setLineWidth(lineWidth);
422
 
            visibleTextLength += line.textLength();
423
 
 
424
 
            if (--linesLeft == 0) {
425
 
                if (visibleTextLength < text.length()) {
426
 
                    truncate = true;
427
 
                    if (elideMode==QDeclarativeText::ElideRight && q->widthValid()) {
428
 
                        qreal elideWidth = fm.width(elideChar);
429
 
                        // Need to correct for alignment
430
 
                        line.setLineWidth(lineWidth-elideWidth);
431
 
                        if (layout.text().mid(line.textStart(), line.textLength()).isRightToLeft()) {
432
 
                            line.setPosition(QPointF(line.position().x() + elideWidth, line.position().y()));
433
 
                            elidePos.setX(line.naturalTextRect().left() - elideWidth);
434
 
                        } else {
435
 
                            elidePos.setX(line.naturalTextRect().right());
436
 
                        }
437
 
                        elideText = true;
438
 
                    }
439
 
                }
440
 
            }
441
 
        }
442
 
        layout.endLayout();
443
 
 
444
 
        //Update truncated
445
 
        if (truncated != truncate) {
446
 
            truncated = truncate;
447
 
            emit q->truncatedChanged();
448
 
        }
449
 
    } else {
450
 
        layout.beginLayout();
451
 
        forever {
452
 
            QTextLine line = layout.createLine();
453
 
            if (!line.isValid())
454
 
                break;
455
 
            visibleCount++;
456
 
            if (lineWidth)
457
 
                line.setLineWidth(lineWidth);
458
 
        }
459
 
        layout.endLayout();
460
 
    }
461
 
 
462
 
    qreal height = 0;
463
 
    QRectF br;
464
 
    for (int i = 0; i < layout.lineCount(); ++i) {
465
 
        QTextLine line = layout.lineAt(i);
466
 
        // set line spacing
467
 
        line.setPosition(QPointF(line.position().x(), height));
468
 
        if (elideText && i == layout.lineCount()-1) {
469
 
            elidePos.setY(height + fm.ascent());
470
 
            br = br.united(QRectF(elidePos, QSizeF(fm.width(elideChar), fm.ascent())));
471
 
        }
472
 
        br = br.united(line.naturalTextRect());
473
 
        height += (lineHeightMode == QDeclarativeText::FixedHeight) ? lineHeight : line.height() * lineHeight;
474
 
    }
475
 
    br.setHeight(height);
476
 
 
477
 
    if (!q->widthValid())
478
 
        naturalWidth = br.width();
479
 
 
480
 
    //Update the number of visible lines
481
 
    if (lineCount != visibleCount) {
482
 
        lineCount = visibleCount;
483
 
        emit q->lineCountChanged();
484
 
    }
485
 
 
486
 
    return QRect(qRound(br.x()), qRound(br.y()), qCeil(br.width()), qCeil(br.height()));
487
 
}
488
 
 
489
 
/*!
490
 
    Returns a painted version of the QDeclarativeTextPrivate::layout QTextLayout.
491
 
    If \a drawStyle is true, the style color overrides all colors in the document.
492
 
*/
493
 
QPixmap QDeclarativeTextPrivate::textLayoutImage(bool drawStyle)
494
 
{
495
 
    //do layout
496
 
    QSize size = layedOutTextRect.size();
497
 
    //paint text
498
 
    QPixmap img(size);
499
 
    if (!size.isEmpty()) {
500
 
        img.fill(Qt::transparent);
501
 
#ifdef Q_WS_MAC
502
 
        bool oldSmooth = qt_applefontsmoothing_enabled;
503
 
        qt_applefontsmoothing_enabled = false;
504
 
#endif
505
 
        QPainter p(&img);
506
 
#ifdef Q_WS_MAC
507
 
        qt_applefontsmoothing_enabled = oldSmooth;
508
 
#endif
509
 
        drawTextLayout(&p, QPointF(-layedOutTextRect.x(),0), drawStyle);
510
 
    }
511
 
    return img;
512
 
}
513
 
 
514
 
/*!
515
 
    Paints the QDeclarativeTextPrivate::layout QTextLayout into \a painter at \a pos.  If 
516
 
    \a drawStyle is true, the style color overrides all colors in the document.
517
 
*/
518
 
void QDeclarativeTextPrivate::drawTextLayout(QPainter *painter, const QPointF &pos, bool drawStyle)
519
 
{
520
 
    if (drawStyle)
521
 
        painter->setPen(styleColor);
522
 
    else
523
 
        painter->setPen(color);
524
 
    painter->setFont(font);
525
 
    layout.draw(painter, pos);
526
 
    if (!elidePos.isNull())
527
 
        painter->drawText(pos + elidePos, elideChar);
528
 
}
529
 
 
530
 
/*!
531
 
    Returns a painted version of the QDeclarativeTextPrivate::doc QTextDocument.
532
 
    If \a drawStyle is true, the style color overrides all colors in the document.
533
 
*/
534
 
QPixmap QDeclarativeTextPrivate::textDocumentImage(bool drawStyle)
535
 
{
536
 
    QSize size = doc->size().toSize();
537
 
 
538
 
    //paint text
539
 
    QPixmap img(size);
540
 
    img.fill(Qt::transparent);
541
 
#ifdef Q_WS_MAC
542
 
    bool oldSmooth = qt_applefontsmoothing_enabled;
543
 
    qt_applefontsmoothing_enabled = false;
544
 
#endif
545
 
    QPainter p(&img);
546
 
#ifdef Q_WS_MAC
547
 
    qt_applefontsmoothing_enabled = oldSmooth;
548
 
#endif
549
 
 
550
 
    QAbstractTextDocumentLayout::PaintContext context;
551
 
 
552
 
    QTextOption oldOption(doc->defaultTextOption());
553
 
    if (drawStyle) {
554
 
        context.palette.setColor(QPalette::Text, styleColor);
555
 
        QTextOption colorOption(doc->defaultTextOption());
556
 
        colorOption.setFlags(QTextOption::SuppressColors);
557
 
        doc->setDefaultTextOption(colorOption);
558
 
    } else {
559
 
        context.palette.setColor(QPalette::Text, color);
560
 
    }
561
 
    doc->documentLayout()->draw(&p, context);
562
 
    if (drawStyle)
563
 
        doc->setDefaultTextOption(oldOption);
564
 
    return img;
565
 
}
566
 
 
567
 
/*!
568
 
    Mark the image cache as dirty.
569
 
*/
570
 
void QDeclarativeTextPrivate::invalidateImageCache() 
571
 
{
572
 
    Q_Q(QDeclarativeText);
573
 
 
574
 
    if(cacheAllTextAsImage || style != QDeclarativeText::Normal){//If actually using the image cache
575
 
        if (imageCacheDirty)
576
 
            return;
577
 
 
578
 
        imageCacheDirty = true;
579
 
        imageCache = QPixmap();
580
 
    }
581
 
    if (q->isComponentComplete())
582
 
        q->update();
583
 
}
584
 
 
585
 
/*!
586
 
    Tests if the image cache is dirty, and repaints it if it is.
587
 
*/
588
 
void QDeclarativeTextPrivate::checkImageCache()
589
 
{
590
 
    if (!imageCacheDirty)
591
 
        return;
592
 
 
593
 
    if (text.isEmpty()) {
594
 
 
595
 
        imageCache = QPixmap();
596
 
 
597
 
    } else {
598
 
 
599
 
        QPixmap textImage;
600
 
        QPixmap styledImage;
601
 
 
602
 
        if (richText) {
603
 
            textImage = textDocumentImage(false);
604
 
            if (style != QDeclarativeText::Normal)
605
 
                styledImage = textDocumentImage(true); //### should use styleColor
606
 
        } else {
607
 
            textImage = textLayoutImage(false);
608
 
            if (style != QDeclarativeText::Normal)
609
 
                styledImage = textLayoutImage(true); //### should use styleColor
610
 
        }
611
 
 
612
 
        switch (style) {
613
 
        case QDeclarativeText::Outline:
614
 
            imageCache = drawOutline(textImage, styledImage);
615
 
            break;
616
 
        case QDeclarativeText::Sunken:
617
 
            imageCache = drawOutline(textImage, styledImage, -1);
618
 
            break;
619
 
        case QDeclarativeText::Raised:
620
 
            imageCache = drawOutline(textImage, styledImage, 1);
621
 
            break;
622
 
        default:
623
 
            imageCache = textImage;
624
 
            break;
625
 
        }
626
 
 
627
 
    } 
628
 
 
629
 
    imageCacheDirty = false;
630
 
}
631
 
 
632
 
/*! 
633
 
    Ensures the QDeclarativeTextPrivate::doc variable is set to a valid text document 
634
 
*/
635
 
void QDeclarativeTextPrivate::ensureDoc()
636
 
{
637
 
    if (!doc) {
638
 
        Q_Q(QDeclarativeText);
639
 
        doc = new QTextDocumentWithImageResources(q);
640
 
        doc->setDocumentMargin(0);
641
 
    }
642
 
}
643
 
 
644
 
/*!
645
 
    Draw \a styleSource as an outline around \a source and return the new image.
646
 
*/
647
 
QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource)
648
 
{
649
 
    QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
650
 
    img.fill(Qt::transparent);
651
 
 
652
 
    QPainter ppm(&img);
653
 
 
654
 
    QPoint pos(0, 0);
655
 
    pos += QPoint(-1, 0);
656
 
    ppm.drawPixmap(pos, styleSource);
657
 
    pos += QPoint(2, 0);
658
 
    ppm.drawPixmap(pos, styleSource);
659
 
    pos += QPoint(-1, -1);
660
 
    ppm.drawPixmap(pos, styleSource);
661
 
    pos += QPoint(0, 2);
662
 
    ppm.drawPixmap(pos, styleSource);
663
 
 
664
 
    pos += QPoint(0, -1);
665
 
    ppm.drawPixmap(pos, source);
666
 
    ppm.end();
667
 
 
668
 
    return img;
669
 
}
670
 
 
671
 
/*!
672
 
    Draw \a styleSource below \a source at \a yOffset and return the new image.
673
 
*/
674
 
QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset)
675
 
{
676
 
    QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
677
 
    img.fill(Qt::transparent);
678
 
 
679
 
    QPainter ppm(&img);
680
 
 
681
 
    ppm.drawPixmap(QPoint(0, yOffset), styleSource);
682
 
    ppm.drawPixmap(0, 0, source);
683
 
 
684
 
    ppm.end();
685
 
 
686
 
    return img;
687
 
}
688
 
 
689
 
/*!
690
 
    \qmlclass Text QDeclarativeText
691
 
    \ingroup qml-basic-visual-elements
692
 
    \since 4.7
693
 
    \brief The Text item allows you to add formatted text to a scene.
694
 
    \inherits Item
695
 
 
696
 
    Text items can display both plain and rich text. For example, red text with
697
 
    a specific font and size can be defined like this:
698
 
 
699
 
    \qml
700
 
    Text {
701
 
        text: "Hello World!"
702
 
        font.family: "Helvetica"
703
 
        font.pointSize: 24
704
 
        color: "red"
705
 
    }
706
 
    \endqml
707
 
 
708
 
    Rich text is defined using HTML-style markup:
709
 
 
710
 
    \qml
711
 
    Text {
712
 
        text: "<b>Hello</b> <i>World!</i>"
713
 
    }
714
 
    \endqml
715
 
 
716
 
    \image declarative-text.png
717
 
 
718
 
    If height and width are not explicitly set, Text will attempt to determine how
719
 
    much room is needed and set it accordingly. Unless \l wrapMode is set, it will always
720
 
    prefer width to height (all text will be placed on a single line).
721
 
 
722
 
    The \l elide property can alternatively be used to fit a single line of
723
 
    plain text to a set width.
724
 
 
725
 
    Note that the \l{Supported HTML Subset} is limited. Also, if the text contains
726
 
    HTML img tags that load remote images, the text is reloaded.
727
 
 
728
 
    Text provides read-only text. For editable text, see \l TextEdit.
729
 
 
730
 
    \sa {declarative/text/fonts}{Fonts example}
731
 
*/
732
 
QDeclarativeText::QDeclarativeText(QDeclarativeItem *parent)
733
 
  : QDeclarativeImplicitSizeItem(*(new QDeclarativeTextPrivate), parent)
734
 
{
735
 
}
736
 
 
737
 
QDeclarativeText::~QDeclarativeText()
738
 
{
739
 
}
740
 
 
741
 
/*!
742
 
  \qmlproperty bool Text::clip
743
 
  This property holds whether the text is clipped.
744
 
 
745
 
  Note that if the text does not fit in the bounding rectangle it will be abruptly chopped.
746
 
 
747
 
  If you want to display potentially long text in a limited space, you probably want to use \c elide instead.
748
 
*/
749
 
 
750
 
/*!
751
 
    \qmlproperty bool Text::smooth
752
 
 
753
 
    This property holds whether the text is smoothly scaled or transformed.
754
 
 
755
 
    Smooth filtering gives better visual quality, but is slower.  If
756
 
    the item is displayed at its natural size, this property has no visual or
757
 
    performance effect.
758
 
 
759
 
    \note Generally scaling artifacts are only visible if the item is stationary on
760
 
    the screen.  A common pattern when animating an item is to disable smooth
761
 
    filtering at the beginning of the animation and reenable it at the conclusion.
762
 
*/
763
 
 
764
 
/*!
765
 
    \qmlsignal Text::onLinkActivated(string link)
766
 
 
767
 
    This handler is called when the user clicks on a link embedded in the text.
768
 
    The link must be in rich text or HTML format and the 
769
 
    \a link string provides access to the particular link. 
770
 
 
771
 
    \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0
772
 
 
773
 
    The example code will display the text 
774
 
    "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}."
775
 
 
776
 
    Clicking on the highlighted link will output 
777
 
    \tt{http://qt.nokia.com link activated} to the console.
778
 
*/
779
 
 
780
 
/*!
781
 
    \qmlproperty string Text::font.family
782
 
 
783
 
    Sets the family name of the font.
784
 
 
785
 
    The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
786
 
    If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
787
 
    If the family isn't available a family will be set using the font matching algorithm.
788
 
*/
789
 
 
790
 
/*!
791
 
    \qmlproperty bool Text::font.bold
792
 
 
793
 
    Sets whether the font weight is bold.
794
 
*/
795
 
 
796
 
/*!
797
 
    \qmlproperty enumeration Text::font.weight
798
 
 
799
 
    Sets the font's weight.
800
 
 
801
 
    The weight can be one of:
802
 
    \list
803
 
    \o Font.Light
804
 
    \o Font.Normal - the default
805
 
    \o Font.DemiBold
806
 
    \o Font.Bold
807
 
    \o Font.Black
808
 
    \endlist
809
 
 
810
 
    \qml
811
 
    Text { text: "Hello"; font.weight: Font.DemiBold }
812
 
    \endqml
813
 
*/
814
 
 
815
 
/*!
816
 
    \qmlproperty bool Text::font.italic
817
 
 
818
 
    Sets whether the font has an italic style.
819
 
*/
820
 
 
821
 
/*!
822
 
    \qmlproperty bool Text::font.underline
823
 
 
824
 
    Sets whether the text is underlined.
825
 
*/
826
 
 
827
 
/*!
828
 
    \qmlproperty bool Text::font.strikeout
829
 
 
830
 
    Sets whether the font has a strikeout style.
831
 
*/
832
 
 
833
 
/*!
834
 
    \qmlproperty real Text::font.pointSize
835
 
 
836
 
    Sets the font size in points. The point size must be greater than zero.
837
 
*/
838
 
 
839
 
/*!
840
 
    \qmlproperty int Text::font.pixelSize
841
 
 
842
 
    Sets the font size in pixels.
843
 
 
844
 
    Using this function makes the font device dependent.
845
 
    Use \c pointSize to set the size of the font in a device independent manner.
846
 
*/
847
 
 
848
 
/*!
849
 
    \qmlproperty real Text::font.letterSpacing
850
 
 
851
 
    Sets the letter spacing for the font.
852
 
 
853
 
    Letter spacing changes the default spacing between individual letters in the font.
854
 
    A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
855
 
*/
856
 
 
857
 
/*!
858
 
    \qmlproperty real Text::font.wordSpacing
859
 
 
860
 
    Sets the word spacing for the font.
861
 
 
862
 
    Word spacing changes the default spacing between individual words.
863
 
    A positive value increases the word spacing by a corresponding amount of pixels,
864
 
    while a negative value decreases the inter-word spacing accordingly.
865
 
*/
866
 
 
867
 
/*!
868
 
    \qmlproperty enumeration Text::font.capitalization
869
 
 
870
 
    Sets the capitalization for the text.
871
 
 
872
 
    \list
873
 
    \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
874
 
    \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
875
 
    \o Font.AllLowercase         - This alters the text to be rendered in all lowercase type.
876
 
    \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
877
 
    \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
878
 
    \endlist
879
 
 
880
 
    \qml
881
 
    Text { text: "Hello"; font.capitalization: Font.AllLowercase }
882
 
    \endqml
883
 
*/
884
 
QFont QDeclarativeText::font() const
885
 
{
886
 
    Q_D(const QDeclarativeText);
887
 
    return d->sourceFont;
888
 
}
889
 
 
890
 
void QDeclarativeText::setFont(const QFont &font)
891
 
{
892
 
    Q_D(QDeclarativeText);
893
 
    if (d->sourceFont == font)
894
 
        return;
895
 
 
896
 
    d->sourceFont = font;
897
 
    QFont oldFont = d->font;
898
 
    d->font = font;
899
 
    if (d->font.pointSizeF() != -1) {
900
 
        // 0.5pt resolution
901
 
        qreal size = qRound(d->font.pointSizeF()*2.0);
902
 
        d->font.setPointSizeF(size/2.0);
903
 
    }
904
 
 
905
 
    if (oldFont != d->font)
906
 
        d->updateLayout();
907
 
 
908
 
    emit fontChanged(d->sourceFont);
909
 
}
910
 
 
911
 
/*!
912
 
    \qmlproperty string Text::text
913
 
 
914
 
    The text to display. Text supports both plain and rich text strings.
915
 
 
916
 
    The item will try to automatically determine whether the text should
917
 
    be treated as rich text. This determination is made using Qt::mightBeRichText().
918
 
*/
919
 
QString QDeclarativeText::text() const
920
 
{
921
 
    Q_D(const QDeclarativeText);
922
 
    return d->text;
923
 
}
924
 
 
925
 
void QDeclarativeText::setText(const QString &n)
926
 
{
927
 
    Q_D(QDeclarativeText);
928
 
    if (d->text == n)
929
 
        return;
930
 
 
931
 
    d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n));
932
 
    d->text = n;
933
 
    if (isComponentComplete()) {
934
 
        if (d->richText) {
935
 
            d->ensureDoc();
936
 
            d->doc->setText(n);
937
 
            d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
938
 
        } else {
939
 
            d->rightToLeftText = d->text.isRightToLeft();
940
 
        }
941
 
        d->determineHorizontalAlignment();
942
 
    }
943
 
    d->updateLayout();
944
 
    emit textChanged(d->text);
945
 
}
946
 
 
947
 
 
948
 
/*!
949
 
    \qmlproperty color Text::color
950
 
 
951
 
    The text color.
952
 
 
953
 
    An example of green text defined using hexadecimal notation:
954
 
    \qml
955
 
    Text {
956
 
        color: "#00FF00"
957
 
        text: "green text"
958
 
    }
959
 
    \endqml
960
 
 
961
 
    An example of steel blue text defined using an SVG color name:
962
 
    \qml
963
 
    Text {
964
 
        color: "steelblue"
965
 
        text: "blue text"
966
 
    }
967
 
    \endqml
968
 
*/
969
 
QColor QDeclarativeText::color() const
970
 
{
971
 
    Q_D(const QDeclarativeText);
972
 
    return d->color;
973
 
}
974
 
 
975
 
void QDeclarativeText::setColor(const QColor &color)
976
 
{
977
 
    Q_D(QDeclarativeText);
978
 
    if (d->color == color)
979
 
        return;
980
 
 
981
 
    d->color = color;
982
 
    d->invalidateImageCache();
983
 
    emit colorChanged(d->color);
984
 
}
985
 
 
986
 
/*!
987
 
    \qmlproperty enumeration Text::style
988
 
 
989
 
    Set an additional text style.
990
 
 
991
 
    Supported text styles are:
992
 
    \list
993
 
    \o Text.Normal - the default
994
 
    \o Text.Outline
995
 
    \o Text.Raised
996
 
    \o Text.Sunken
997
 
    \endlist
998
 
 
999
 
    \qml
1000
 
    Row {
1001
 
        Text { font.pointSize: 24; text: "Normal" }
1002
 
        Text { font.pointSize: 24; text: "Raised"; style: Text.Raised; styleColor: "#AAAAAA" }
1003
 
        Text { font.pointSize: 24; text: "Outline";style: Text.Outline; styleColor: "red" }
1004
 
        Text { font.pointSize: 24; text: "Sunken"; style: Text.Sunken; styleColor: "#AAAAAA" }
1005
 
    }
1006
 
    \endqml
1007
 
 
1008
 
    \image declarative-textstyle.png
1009
 
*/
1010
 
QDeclarativeText::TextStyle QDeclarativeText::style() const
1011
 
{
1012
 
    Q_D(const QDeclarativeText);
1013
 
    return d->style;
1014
 
}
1015
 
 
1016
 
void QDeclarativeText::setStyle(QDeclarativeText::TextStyle style)
1017
 
{
1018
 
    Q_D(QDeclarativeText);
1019
 
    if (d->style == style)
1020
 
        return;
1021
 
 
1022
 
    // changing to/from Normal requires the boundingRect() to change
1023
 
    if (isComponentComplete() && (d->style == Normal || style == Normal))
1024
 
        prepareGeometryChange();
1025
 
    d->style = style;
1026
 
    d->invalidateImageCache();
1027
 
    emit styleChanged(d->style);
1028
 
}
1029
 
 
1030
 
/*!
1031
 
    \qmlproperty color Text::styleColor
1032
 
 
1033
 
    Defines the secondary color used by text styles.
1034
 
 
1035
 
    \c styleColor is used as the outline color for outlined text, and as the
1036
 
    shadow color for raised or sunken text. If no style has been set, it is not
1037
 
    used at all.
1038
 
 
1039
 
    \qml
1040
 
    Text { font.pointSize: 18; text: "hello"; style: Text.Raised; styleColor: "gray" }
1041
 
    \endqml
1042
 
 
1043
 
    \sa style
1044
 
 */
1045
 
QColor QDeclarativeText::styleColor() const
1046
 
{
1047
 
    Q_D(const QDeclarativeText);
1048
 
    return d->styleColor;
1049
 
}
1050
 
 
1051
 
void QDeclarativeText::setStyleColor(const QColor &color)
1052
 
{
1053
 
    Q_D(QDeclarativeText);
1054
 
    if (d->styleColor == color)
1055
 
        return;
1056
 
 
1057
 
    d->styleColor = color;
1058
 
    d->invalidateImageCache();
1059
 
    emit styleColorChanged(d->styleColor);
1060
 
}
1061
 
 
1062
 
 
1063
 
/*!
1064
 
    \qmlproperty enumeration Text::horizontalAlignment
1065
 
    \qmlproperty enumeration Text::verticalAlignment
1066
 
 
1067
 
    Sets the horizontal and vertical alignment of the text within the Text items
1068
 
    width and height. By default, the text is vertically aligned to the top. Horizontal
1069
 
    alignment follows the natural alignment of the text, for example text that is read
1070
 
    from left to right will be aligned to the left.
1071
 
 
1072
 
    The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight, \c Text.AlignHCenter and
1073
 
    \c Text.AlignJustify.  The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom
1074
 
    and \c Text.AlignVCenter.
1075
 
 
1076
 
    Note that for a single line of text, the size of the text is the area of the text. In this common case,
1077
 
    all alignments are equivalent. If you want the text to be, say, centered in its parent, then you will
1078
 
    need to either modify the Item::anchors, or set horizontalAlignment to Text.AlignHCenter and bind the width to 
1079
 
    that of the parent.
1080
 
 
1081
 
    When using the attached property \l {LayoutMirroring::enabled} to mirror application
1082
 
    layouts, the horizontal alignment of text will also be mirrored. However, the property
1083
 
    \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
1084
 
    of Text, use the property \l {LayoutMirroring::enabled}.
1085
 
*/
1086
 
QDeclarativeText::HAlignment QDeclarativeText::hAlign() const
1087
 
{
1088
 
    Q_D(const QDeclarativeText);
1089
 
    return d->hAlign;
1090
 
}
1091
 
 
1092
 
void QDeclarativeText::setHAlign(HAlignment align)
1093
 
{
1094
 
    Q_D(QDeclarativeText);
1095
 
    bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
1096
 
    d->hAlignImplicit = false;
1097
 
    if (d->setHAlign(align, forceAlign) && isComponentComplete())
1098
 
        d->updateLayout();
1099
 
}
1100
 
 
1101
 
void QDeclarativeText::resetHAlign()
1102
 
{
1103
 
    Q_D(QDeclarativeText);
1104
 
    d->hAlignImplicit = true;
1105
 
    if (d->determineHorizontalAlignment() && isComponentComplete())
1106
 
        d->updateLayout();
1107
 
}
1108
 
 
1109
 
QDeclarativeText::HAlignment QDeclarativeText::effectiveHAlign() const
1110
 
{
1111
 
    Q_D(const QDeclarativeText);
1112
 
    QDeclarativeText::HAlignment effectiveAlignment = d->hAlign;
1113
 
    if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
1114
 
        switch (d->hAlign) {
1115
 
        case QDeclarativeText::AlignLeft:
1116
 
            effectiveAlignment = QDeclarativeText::AlignRight;
1117
 
            break;
1118
 
        case QDeclarativeText::AlignRight:
1119
 
            effectiveAlignment = QDeclarativeText::AlignLeft;
1120
 
            break;
1121
 
        default:
1122
 
            break;
1123
 
        }
1124
 
    }
1125
 
    return effectiveAlignment;
1126
 
}
1127
 
 
1128
 
bool QDeclarativeTextPrivate::setHAlign(QDeclarativeText::HAlignment alignment, bool forceAlign)
1129
 
{
1130
 
    Q_Q(QDeclarativeText);
1131
 
    if (hAlign != alignment || forceAlign) {
1132
 
        QDeclarativeText::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
1133
 
        hAlign = alignment;
1134
 
        emit q->horizontalAlignmentChanged(hAlign);
1135
 
        return true;
1136
 
    }
1137
 
    return false;
1138
 
}
1139
 
 
1140
 
bool QDeclarativeTextPrivate::determineHorizontalAlignment()
1141
 
{
1142
 
    Q_Q(QDeclarativeText);
1143
 
    if (hAlignImplicit && q->isComponentComplete()) {
1144
 
        bool alignToRight = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : rightToLeftText;
1145
 
        return setHAlign(alignToRight ? QDeclarativeText::AlignRight : QDeclarativeText::AlignLeft);
1146
 
    }
1147
 
    return false;
1148
 
}
1149
 
 
1150
 
void QDeclarativeTextPrivate::mirrorChange()
1151
 
{
1152
 
    Q_Q(QDeclarativeText);
1153
 
    if (q->isComponentComplete()) {
1154
 
        if (!hAlignImplicit && (hAlign == QDeclarativeText::AlignRight || hAlign == QDeclarativeText::AlignLeft)) {
1155
 
            updateLayout();
1156
 
        }
1157
 
    }
1158
 
}
1159
 
 
1160
 
QTextDocument *QDeclarativeTextPrivate::textDocument()
1161
 
{
1162
 
    return doc;
1163
 
}
1164
 
 
1165
 
QDeclarativeText::VAlignment QDeclarativeText::vAlign() const
1166
 
{
1167
 
    Q_D(const QDeclarativeText);
1168
 
    return d->vAlign;
1169
 
}
1170
 
 
1171
 
void QDeclarativeText::setVAlign(VAlignment align)
1172
 
{
1173
 
    Q_D(QDeclarativeText);
1174
 
    if (d->vAlign == align)
1175
 
        return;
1176
 
 
1177
 
    if (isComponentComplete())
1178
 
        prepareGeometryChange();
1179
 
    d->vAlign = align;
1180
 
    emit verticalAlignmentChanged(align);
1181
 
}
1182
 
 
1183
 
/*!
1184
 
    \qmlproperty enumeration Text::wrapMode
1185
 
 
1186
 
    Set this property to wrap the text to the Text item's width.  The text will only
1187
 
    wrap if an explicit width has been set.  wrapMode can be one of:
1188
 
 
1189
 
    \list
1190
 
    \o Text.NoWrap (default) - no wrapping will be performed. If the text contains insufficient newlines, then \l paintedWidth will exceed a set width.
1191
 
    \o Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, \l paintedWidth will exceed a set width.
1192
 
    \o Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
1193
 
    \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.
1194
 
    \endlist
1195
 
*/
1196
 
QDeclarativeText::WrapMode QDeclarativeText::wrapMode() const
1197
 
{
1198
 
    Q_D(const QDeclarativeText);
1199
 
    return d->wrapMode;
1200
 
}
1201
 
 
1202
 
void QDeclarativeText::setWrapMode(WrapMode mode)
1203
 
{
1204
 
    Q_D(QDeclarativeText);
1205
 
    if (mode == d->wrapMode)
1206
 
        return;
1207
 
 
1208
 
    d->wrapMode = mode;
1209
 
    d->updateLayout();
1210
 
    
1211
 
    emit wrapModeChanged();
1212
 
}
1213
 
 
1214
 
/*!
1215
 
    \qmlproperty int Text::lineCount
1216
 
    \since QtQuick 1.1
1217
 
 
1218
 
    Returns the number of lines visible in the text item.
1219
 
 
1220
 
    This property is not supported for rich text.
1221
 
 
1222
 
    \sa maximumLineCount
1223
 
*/
1224
 
int QDeclarativeText::lineCount() const
1225
 
{
1226
 
    Q_D(const QDeclarativeText);
1227
 
    return d->lineCount;
1228
 
}
1229
 
 
1230
 
/*!
1231
 
    \qmlproperty bool Text::truncated
1232
 
    \since QtQuick 1.1
1233
 
 
1234
 
    Returns true if the text has been truncated due to \l maximumLineCount
1235
 
    or \l elide.
1236
 
 
1237
 
    This property is not supported for rich text.
1238
 
 
1239
 
    \sa maximumLineCount, elide
1240
 
*/
1241
 
bool QDeclarativeText::truncated() const
1242
 
{
1243
 
    Q_D(const QDeclarativeText);
1244
 
    return d->truncated;
1245
 
}
1246
 
 
1247
 
/*!
1248
 
    \qmlproperty int Text::maximumLineCount
1249
 
    \since QtQuick 1.1
1250
 
 
1251
 
    Set this property to limit the number of lines that the text item will show.
1252
 
    If elide is set to Text.ElideRight, the text will be elided appropriately.
1253
 
    By default, this is the value of the largest possible integer.
1254
 
 
1255
 
    This property is not supported for rich text.
1256
 
 
1257
 
    \sa lineCount, elide
1258
 
*/
1259
 
int QDeclarativeText::maximumLineCount() const
1260
 
{
1261
 
    Q_D(const QDeclarativeText);
1262
 
    return d->maximumLineCount;
1263
 
}
1264
 
 
1265
 
void QDeclarativeText::setMaximumLineCount(int lines)
1266
 
{
1267
 
    Q_D(QDeclarativeText);
1268
 
 
1269
 
    d->maximumLineCountValid = lines==INT_MAX ? false : true;
1270
 
    if (d->maximumLineCount != lines) {
1271
 
        d->maximumLineCount = lines;
1272
 
        d->updateLayout();
1273
 
        emit maximumLineCountChanged();
1274
 
    }
1275
 
}
1276
 
 
1277
 
void QDeclarativeText::resetMaximumLineCount()
1278
 
{
1279
 
    Q_D(QDeclarativeText);
1280
 
    setMaximumLineCount(INT_MAX);
1281
 
    d->elidePos = QPointF();
1282
 
    if (d->truncated != false) {
1283
 
        d->truncated = false;
1284
 
        emit truncatedChanged();
1285
 
    }
1286
 
}
1287
 
 
1288
 
/*!
1289
 
    \qmlproperty enumeration Text::textFormat
1290
 
 
1291
 
    The way the text property should be displayed.
1292
 
 
1293
 
    Supported text formats are:
1294
 
    
1295
 
    \list
1296
 
    \o Text.AutoText (default)
1297
 
    \o Text.PlainText
1298
 
    \o Text.RichText
1299
 
    \o Text.StyledText
1300
 
    \endlist
1301
 
 
1302
 
    If the text format is \c Text.AutoText the text element
1303
 
    will automatically determine whether the text should be treated as
1304
 
    rich text.  This determination is made using Qt::mightBeRichText().
1305
 
 
1306
 
    Text.StyledText is an optimized format supporting some basic text
1307
 
    styling markup, in the style of html 3.2:
1308
 
 
1309
 
    \code
1310
 
    <font size="4" color="#ff0000">font size and color</font>
1311
 
    <b>bold</b>
1312
 
    <i>italic</i>
1313
 
    <br>
1314
 
    &gt; &lt; &amp;
1315
 
    \endcode
1316
 
 
1317
 
    \c Text.StyledText parser is strict, requiring tags to be correctly nested.
1318
 
 
1319
 
    \table
1320
 
    \row
1321
 
    \o
1322
 
    \qml
1323
 
Column {
1324
 
    Text {
1325
 
        font.pointSize: 24
1326
 
        text: "<b>Hello</b> <i>World!</i>"
1327
 
    }
1328
 
    Text {
1329
 
        font.pointSize: 24
1330
 
        textFormat: Text.RichText
1331
 
        text: "<b>Hello</b> <i>World!</i>"
1332
 
    }
1333
 
    Text {
1334
 
        font.pointSize: 24
1335
 
        textFormat: Text.PlainText
1336
 
        text: "<b>Hello</b> <i>World!</i>"
1337
 
    }
1338
 
}
1339
 
    \endqml
1340
 
    \o \image declarative-textformat.png
1341
 
    \endtable
1342
 
*/
1343
 
QDeclarativeText::TextFormat QDeclarativeText::textFormat() const
1344
 
{
1345
 
    Q_D(const QDeclarativeText);
1346
 
    return d->format;
1347
 
}
1348
 
 
1349
 
void QDeclarativeText::setTextFormat(TextFormat format)
1350
 
{
1351
 
    Q_D(QDeclarativeText);
1352
 
    if (format == d->format)
1353
 
        return;
1354
 
    d->format = format;
1355
 
    bool wasRich = d->richText;
1356
 
    d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
1357
 
 
1358
 
    if (!wasRich && d->richText && isComponentComplete()) {
1359
 
        d->ensureDoc();
1360
 
        d->doc->setText(d->text);
1361
 
    }
1362
 
 
1363
 
    d->updateLayout();
1364
 
 
1365
 
    emit textFormatChanged(d->format);
1366
 
}
1367
 
 
1368
 
/*!
1369
 
    \qmlproperty enumeration Text::elide
1370
 
 
1371
 
    Set this property to elide parts of the text fit to the Text item's width.
1372
 
    The text will only elide if an explicit width has been set.
1373
 
 
1374
 
    This property cannot be used with rich text.
1375
 
 
1376
 
    Eliding can be:
1377
 
    \list
1378
 
    \o Text.ElideNone  - the default
1379
 
    \o Text.ElideLeft
1380
 
    \o Text.ElideMiddle
1381
 
    \o Text.ElideRight
1382
 
    \endlist
1383
 
 
1384
 
    If this property is set to Text.ElideRight, it can be used with multiline
1385
 
    text. The text will only elide if maximumLineCount has been set.
1386
 
 
1387
 
    If the text is a multi-length string, and the mode is not \c Text.ElideNone,
1388
 
    the first string that fits will be used, otherwise the last will be elided.
1389
 
 
1390
 
    Multi-length strings are ordered from longest to shortest, separated by the
1391
 
    Unicode "String Terminator" character \c U009C (write this in QML with \c{"\u009C"} or \c{"\x9C"}).
1392
 
*/
1393
 
QDeclarativeText::TextElideMode QDeclarativeText::elideMode() const
1394
 
{
1395
 
    Q_D(const QDeclarativeText);
1396
 
    return d->elideMode;
1397
 
}
1398
 
 
1399
 
void QDeclarativeText::setElideMode(QDeclarativeText::TextElideMode mode)
1400
 
{
1401
 
    Q_D(QDeclarativeText);
1402
 
    if (mode == d->elideMode)
1403
 
        return;
1404
 
 
1405
 
    d->elideMode = mode;
1406
 
    d->updateLayout();
1407
 
    
1408
 
    emit elideModeChanged(d->elideMode);
1409
 
}
1410
 
 
1411
 
/*! \internal */
1412
 
QRectF QDeclarativeText::boundingRect() const
1413
 
{
1414
 
    Q_D(const QDeclarativeText);
1415
 
 
1416
 
    QRect rect = d->layedOutTextRect;
1417
 
    if (d->style != Normal)
1418
 
        rect.adjust(-1, 0, 1, 2);
1419
 
 
1420
 
    // Could include font max left/right bearings to either side of rectangle.
1421
 
 
1422
 
    int h = height();
1423
 
    switch (d->vAlign) {
1424
 
    case AlignTop:
1425
 
        break;
1426
 
    case AlignBottom:
1427
 
        rect.moveTop(h - rect.height());
1428
 
        break;
1429
 
    case AlignVCenter:
1430
 
        rect.moveTop((h - rect.height()) / 2);
1431
 
        break;
1432
 
    }
1433
 
 
1434
 
    return QRectF(rect);
1435
 
}
1436
 
 
1437
 
/*! \internal */
1438
 
void QDeclarativeText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
1439
 
{
1440
 
    Q_D(QDeclarativeText);
1441
 
    if ((!d->internalWidthUpdate && newGeometry.width() != oldGeometry.width())
1442
 
            && (d->wrapMode != QDeclarativeText::NoWrap
1443
 
                || d->elideMode != QDeclarativeText::ElideNone
1444
 
                || d->hAlign != QDeclarativeText::AlignLeft)) {
1445
 
        if ((d->singleline || d->maximumLineCountValid) && d->elideMode != QDeclarativeText::ElideNone && widthValid()) {
1446
 
            // We need to re-elide
1447
 
            d->updateLayout();
1448
 
        } else {
1449
 
            // We just need to re-layout
1450
 
            d->updateSize();
1451
 
        }
1452
 
    }
1453
 
 
1454
 
    QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
1455
 
}
1456
 
 
1457
 
/*!
1458
 
    \qmlproperty real Text::paintedWidth
1459
 
 
1460
 
    Returns the width of the text, including width past the width
1461
 
    which is covered due to insufficient wrapping if WrapMode is set.
1462
 
*/
1463
 
qreal QDeclarativeText::paintedWidth() const
1464
 
{
1465
 
    Q_D(const QDeclarativeText);
1466
 
    return d->paintedSize.width();
1467
 
}
1468
 
 
1469
 
/*!
1470
 
    \qmlproperty real Text::paintedHeight
1471
 
 
1472
 
    Returns the height of the text, including height past the height
1473
 
    which is covered due to there being more text than fits in the set height.
1474
 
*/
1475
 
qreal QDeclarativeText::paintedHeight() const
1476
 
{
1477
 
    Q_D(const QDeclarativeText);
1478
 
    return d->paintedSize.height();
1479
 
}
1480
 
 
1481
 
/*!
1482
 
    \qmlproperty real Text::lineHeight
1483
 
    \since QtQuick 1.1
1484
 
 
1485
 
    Sets the line height for the text.
1486
 
    The value can be in pixels or a multiplier depending on lineHeightMode.
1487
 
 
1488
 
    The default value is a multiplier of 1.0.
1489
 
    The line height must be a positive value.
1490
 
*/
1491
 
qreal QDeclarativeText::lineHeight() const
1492
 
{
1493
 
    Q_D(const QDeclarativeText);
1494
 
    return d->lineHeight;
1495
 
}
1496
 
 
1497
 
void QDeclarativeText::setLineHeight(qreal lineHeight)
1498
 
{
1499
 
    Q_D(QDeclarativeText);
1500
 
 
1501
 
    if ((d->lineHeight == lineHeight) || (lineHeight < 0.0))
1502
 
        return;
1503
 
 
1504
 
    d->lineHeight = lineHeight;
1505
 
    d->updateLayout();
1506
 
    emit lineHeightChanged(lineHeight);
1507
 
}
1508
 
 
1509
 
/*!
1510
 
    \qmlproperty enumeration Text::lineHeightMode
1511
 
 
1512
 
    This property determines how the line height is specified.
1513
 
    The possible values are:
1514
 
 
1515
 
    \list
1516
 
    \o Text.ProportionalHeight (default) - this sets the spacing proportional to the
1517
 
       line (as a multiplier). For example, set to 2 for double spacing.
1518
 
    \o Text.FixedHeight - this sets the line height to a fixed line height (in pixels).
1519
 
    \endlist
1520
 
*/
1521
 
QDeclarativeText::LineHeightMode QDeclarativeText::lineHeightMode() const
1522
 
{
1523
 
    Q_D(const QDeclarativeText);
1524
 
    return d->lineHeightMode;
1525
 
}
1526
 
 
1527
 
void QDeclarativeText::setLineHeightMode(LineHeightMode mode)
1528
 
{
1529
 
    Q_D(QDeclarativeText);
1530
 
    if (mode == d->lineHeightMode)
1531
 
        return;
1532
 
 
1533
 
    d->lineHeightMode = mode;
1534
 
    d->updateLayout();
1535
 
 
1536
 
    emit lineHeightModeChanged(mode);
1537
 
}
1538
 
 
1539
 
/*!
1540
 
    Returns the number of resources (images) that are being loaded asynchronously.
1541
 
*/
1542
 
int QDeclarativeText::resourcesLoading() const
1543
 
{
1544
 
    Q_D(const QDeclarativeText);
1545
 
    return d->doc ? d->doc->resourcesLoading() : 0;
1546
 
}
1547
 
 
1548
 
/*! \internal */
1549
 
void QDeclarativeText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
1550
 
{
1551
 
    Q_D(QDeclarativeText);
1552
 
 
1553
 
    if (d->cacheAllTextAsImage || d->style != Normal) {
1554
 
        d->checkImageCache();
1555
 
        if (d->imageCache.isNull())
1556
 
            return;
1557
 
 
1558
 
        bool oldAA = p->testRenderHint(QPainter::Antialiasing);
1559
 
        bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
1560
 
        if (d->smooth)
1561
 
            p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
1562
 
 
1563
 
        QRect br = boundingRect().toRect();
1564
 
 
1565
 
        bool needClip = clip() && (d->imageCache.width() > width() ||
1566
 
                                   d->imageCache.height() > height());
1567
 
 
1568
 
        if (needClip)
1569
 
            p->drawPixmap(0, 0, width(), height(), d->imageCache, -br.x(), -br.y(), width(), height());
1570
 
        else
1571
 
            p->drawPixmap(br.x(), br.y(), d->imageCache);
1572
 
 
1573
 
        if (d->smooth) {
1574
 
            p->setRenderHint(QPainter::Antialiasing, oldAA);
1575
 
            p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
1576
 
        }
1577
 
    } else {
1578
 
        QRectF bounds = boundingRect();
1579
 
 
1580
 
        bool needClip = clip() && (d->layedOutTextRect.width() > width() ||
1581
 
                                   d->layedOutTextRect.height() > height());
1582
 
 
1583
 
        if (needClip) {
1584
 
            p->save();
1585
 
            p->setClipRect(0, 0, width(), height(), Qt::IntersectClip);
1586
 
        }
1587
 
        if (d->richText) {
1588
 
            QAbstractTextDocumentLayout::PaintContext context;
1589
 
            context.palette.setColor(QPalette::Text, d->color);
1590
 
            p->translate(bounds.x(), bounds.y());
1591
 
            d->doc->documentLayout()->draw(p, context);
1592
 
            p->translate(-bounds.x(), -bounds.y());
1593
 
        } else {
1594
 
            d->drawTextLayout(p, QPointF(0, bounds.y()), false);
1595
 
        }
1596
 
 
1597
 
        if (needClip) {
1598
 
            p->restore();
1599
 
        }
1600
 
    }
1601
 
}
1602
 
 
1603
 
/*! \internal */
1604
 
void QDeclarativeText::componentComplete()
1605
 
{
1606
 
    Q_D(QDeclarativeText);
1607
 
    QDeclarativeItem::componentComplete();
1608
 
    if (d->updateOnComponentComplete) {
1609
 
        d->updateOnComponentComplete = false;
1610
 
        if (d->richText) {
1611
 
            d->ensureDoc();
1612
 
            d->doc->setText(d->text);
1613
 
            d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
1614
 
        } else {
1615
 
            d->rightToLeftText = d->text.isRightToLeft();
1616
 
        }
1617
 
        d->determineHorizontalAlignment();
1618
 
        d->updateLayout();
1619
 
    }
1620
 
}
1621
 
 
1622
 
/*!  \internal */
1623
 
void QDeclarativeText::mousePressEvent(QGraphicsSceneMouseEvent *event)
1624
 
{
1625
 
    Q_D(QDeclarativeText);
1626
 
 
1627
 
    if (!d->richText || !d->doc || d->doc->documentLayout()->anchorAt(event->pos()).isEmpty()) {
1628
 
        event->setAccepted(false);
1629
 
        d->activeLink.clear();
1630
 
    } else {
1631
 
        d->activeLink = d->doc->documentLayout()->anchorAt(event->pos());
1632
 
    }
1633
 
 
1634
 
    // ### may malfunction if two of the same links are clicked & dragged onto each other)
1635
 
 
1636
 
    if (!event->isAccepted())
1637
 
        QDeclarativeItem::mousePressEvent(event);
1638
 
 
1639
 
}
1640
 
 
1641
 
/*! \internal */
1642
 
void QDeclarativeText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1643
 
{
1644
 
    Q_D(QDeclarativeText);
1645
 
 
1646
 
        // ### confirm the link, and send a signal out
1647
 
    if (d->richText && d->doc && d->activeLink == d->doc->documentLayout()->anchorAt(event->pos()))
1648
 
        emit linkActivated(d->activeLink);
1649
 
    else
1650
 
        event->setAccepted(false);
1651
 
 
1652
 
    if (!event->isAccepted())
1653
 
        QDeclarativeItem::mouseReleaseEvent(event);
1654
 
}
1655
 
 
1656
 
QT_END_NAMESPACE
1657
 
 
1658
 
#include "qdeclarativetext.moc"