Qt 4.8
qdeclarativetext.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "private/qdeclarativetext_p.h"
43 #include "private/qdeclarativetext_p_p.h"
45 #include <qdeclarativeinfo.h>
47 
48 #include <QSet>
49 #include <QTextLayout>
50 #include <QTextLine>
51 #include <QTextDocument>
52 #include <QGraphicsSceneMouseEvent>
53 #include <QPainter>
54 #include <QAbstractTextDocumentLayout>
55 #include <qmath.h>
56 #include <limits.h>
57 
59 
61 
63  Q_OBJECT
64 
65 public:
68 
69  void setText(const QString &);
70  int resourcesLoading() const { return outstanding; }
71 
72 protected:
73  QVariant loadResource(int type, const QUrl &name);
74 
75 private slots:
76  void requestFinished();
77 
78 private:
80 
83 };
84 
85 DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE);
86 
88 
90 : color((QRgb)0), style(QDeclarativeText::Normal), hAlign(QDeclarativeText::AlignLeft),
92  format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineHeight(1),
93  lineHeightMode(QDeclarativeText::ProportionalHeight), lineCount(1), truncated(false), maximumLineCount(INT_MAX),
94  maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false),
95  cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), hAlignImplicit(true),
96  rightToLeftText(false), layoutTextElided(false), naturalWidth(0), doc(0)
97 {
98  cacheAllTextAsImage = enableImageCache();
101 }
102 
104 : QTextDocument(parent), outstanding(0)
105 {
106 }
107 
109 {
110  if (!m_resources.isEmpty())
112 }
113 
115 {
116  QDeclarativeContext *context = qmlContext(parent());
117  QUrl url = context->resolvedUrl(name);
118 
119  if (type == QTextDocument::ImageResource) {
121 
122  if (iter == m_resources.end()) {
123  QDeclarativePixmap *p = new QDeclarativePixmap(context->engine(), url);
124  iter = m_resources.insert(name, p);
125 
126  if (p->isLoading()) {
127  p->connectFinished(this, SLOT(requestFinished()));
128  outstanding++;
129  }
130  }
131 
132  QDeclarativePixmap *p = *iter;
133  if (p->isReady()) {
134  return p->pixmap();
135  } else if (p->isError()) {
136  if (!errors.contains(url)) {
137  errors.insert(url);
138  qmlInfo(parent()) << p->error();
139  }
140  }
141  }
142 
143  return QTextDocument::loadResource(type,url); // The *resolved* URL
144 }
145 
147 {
148  outstanding--;
149  if (outstanding == 0) {
150  QDeclarativeText *textItem = static_cast<QDeclarativeText*>(parent());
151  QString text = textItem->text();
152 #ifndef QT_NO_TEXTHTMLPARSER
153  setHtml(text);
154 #else
155  setPlainText(text);
156 #endif
158  d->updateLayout();
159  }
160 }
161 
163 {
164  if (!m_resources.isEmpty()) {
166  m_resources.clear();
167  outstanding = 0;
168  }
169 
170 #ifndef QT_NO_TEXTHTMLPARSER
171  setHtml(text);
172 #else
173  setPlainText(text);
174 #endif
175 }
176 
178 
180 {
181 }
182 
184 {
185  if (!requireImplicitWidth) {
186  // We don't calculate implicitWidth unless it is required.
187  // We need to force a size update now to ensure implicitWidth is calculated
188  QDeclarativeTextPrivate *me = const_cast<QDeclarativeTextPrivate*>(this);
189  me->requireImplicitWidth = true;
190  me->updateSize();
191  }
192  return mImplicitWidth;
193 }
194 
196 {
198  if (!q->isComponentComplete()) {
199  updateOnComponentComplete = true;
200  return;
201  }
202 
203  layoutTextElided = false;
204  // Setup instance of QTextLayout for all cases other than richtext
205  if (!richText) {
206  layout.clearLayout();
207  layout.setFont(font);
209  QString tmp = text;
211  singleline = !tmp.contains(QChar::LineSeparator);
212  if (singleline && !maximumLineCountValid && elideMode != QDeclarativeText::ElideNone && q->widthValid()) {
213  QFontMetrics fm(font);
214  tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width());
215  if (tmp != text) {
216  layoutTextElided = true;
217  if (!truncated) {
218  truncated = true;
219  emit q->truncatedChanged();
220  }
221  }
222  }
223  layout.setText(tmp);
224  } else {
225  singleline = false;
227  }
228  }
229 
230  updateSize();
231 }
232 
234 {
236 
237  if (!q->isComponentComplete()) {
238  updateOnComponentComplete = true;
239  return;
240  }
241 
242  if (!requireImplicitWidth) {
243  emit q->implicitWidthChanged();
244  // if the implicitWidth is used, then updateSize() has already been called (recursively)
245  if (requireImplicitWidth)
246  return;
247  }
248 
249  invalidateImageCache();
250 
251  QFontMetrics fm(font);
252  if (text.isEmpty()) {
253  q->setImplicitWidth(0);
254  q->setImplicitHeight(fm.height());
255  paintedSize = QSize(0, fm.height());
256  emit q->paintedSizeChanged();
257  q->update();
258  return;
259  }
260 
261  int dy = q->height();
262  QSize size(0, 0);
263 
264  //setup instance of QTextLayout for all cases other than richtext
265  if (!richText) {
266  QRect textRect = setupTextLayout();
267  if (layedOutTextRect.size() != textRect.size())
268  q->prepareGeometryChange();
269  layedOutTextRect = textRect;
270  size = textRect.size();
271  dy -= size.height();
272  } else {
273  singleline = false; // richtext can't elide or be optimized for single-line case
274  ensureDoc();
275  doc->setDefaultFont(font);
276 
277  QDeclarativeText::HAlignment horizontalAlignment = q->effectiveHAlign();
278  if (rightToLeftText) {
279  if (horizontalAlignment == QDeclarativeText::AlignLeft)
280  horizontalAlignment = QDeclarativeText::AlignRight;
281  else if (horizontalAlignment == QDeclarativeText::AlignRight)
282  horizontalAlignment = QDeclarativeText::AlignLeft;
283  }
284  QTextOption option;
285  option.setAlignment((Qt::Alignment)int(horizontalAlignment | vAlign));
286  option.setWrapMode(QTextOption::WrapMode(wrapMode));
287  doc->setDefaultTextOption(option);
288  if (requireImplicitWidth && q->widthValid()) {
289  doc->setTextWidth(-1);
290  naturalWidth = doc->idealWidth();
291  }
292  if (q->widthValid())
293  doc->setTextWidth(q->width());
294  else
295  doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
296  dy -= (int)doc->size().height();
297  QSize dsize = doc->size().toSize();
298  if (dsize != layedOutTextRect.size()) {
299  q->prepareGeometryChange();
300  layedOutTextRect = QRect(QPoint(0,0), dsize);
301  }
302  size = QSize(int(doc->idealWidth()),dsize.height());
303  }
304  int yoff = 0;
305 
306  if (q->heightValid()) {
307  if (vAlign == QDeclarativeText::AlignBottom)
308  yoff = dy;
309  else if (vAlign == QDeclarativeText::AlignVCenter)
310  yoff = dy/2;
311  }
312  q->setBaselineOffset(fm.ascent() + yoff);
313 
314  //### need to comfirm cost of always setting these for richText
315  internalWidthUpdate = true;
316  if (!q->widthValid())
317  q->setImplicitWidth(size.width());
318  else if (requireImplicitWidth)
319  q->setImplicitWidth(naturalWidth);
320  internalWidthUpdate = false;
321  q->setImplicitHeight(size.height());
322  if (paintedSize != size) {
323  paintedSize = size;
324  emit q->paintedSizeChanged();
325  }
326  q->update();
327 }
328 
336 {
337  // ### text layout handling should be profiled and optimized as needed
338  // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
340  layout.setCacheEnabled(true);
341 
342  qreal lineWidth = 0;
343  int visibleCount = 0;
344 
345  //set manual width
346  if (q->widthValid())
347  lineWidth = q->width();
348 
349  QTextOption textOption = layout.textOption();
350  textOption.setAlignment(Qt::Alignment(q->effectiveHAlign()));
351  textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
352  layout.setTextOption(textOption);
353 
354  bool elideText = false;
355  bool truncate = false;
356 
357  QFontMetrics fm(layout.font());
358  elidePos = QPointF();
359 
360  if (requireImplicitWidth && q->widthValid()) {
361  // requires an extra layout
362  QString elidedText;
363  if (layoutTextElided) {
364  // We have provided elided text to the layout, but we must calculate unelided width.
365  elidedText = layout.text();
366  layout.setText(text);
367  }
368  layout.beginLayout();
369  forever {
370  QTextLine line = layout.createLine();
371  if (!line.isValid())
372  break;
373  }
374  layout.endLayout();
375  QRectF br;
376  for (int i = 0; i < layout.lineCount(); ++i) {
377  QTextLine line = layout.lineAt(i);
378  br = br.united(line.naturalTextRect());
379  }
380  naturalWidth = br.width();
381  if (layoutTextElided)
382  layout.setText(elidedText);
383  }
384 
385  if (maximumLineCountValid) {
386  layout.beginLayout();
387  if (!lineWidth)
388  lineWidth = INT_MAX;
389  int linesLeft = maximumLineCount;
390  int visibleTextLength = 0;
391  while (linesLeft > 0) {
392  QTextLine line = layout.createLine();
393  if (!line.isValid())
394  break;
395 
396  visibleCount++;
397  if (lineWidth)
398  line.setLineWidth(lineWidth);
399  visibleTextLength += line.textLength();
400 
401  if (--linesLeft == 0) {
402  if (visibleTextLength < text.length()) {
403  truncate = true;
404  if (elideMode==QDeclarativeText::ElideRight && q->widthValid()) {
405  qreal elideWidth = fm.width(elideChar);
406  // Need to correct for alignment
407  line.setLineWidth(lineWidth-elideWidth);
408  if (layout.text().mid(line.textStart(), line.textLength()).isRightToLeft()) {
409  line.setPosition(QPointF(line.position().x() + elideWidth, line.position().y()));
410  elidePos.setX(line.naturalTextRect().left() - elideWidth);
411  } else {
412  elidePos.setX(line.naturalTextRect().right());
413  }
414  elideText = true;
415  }
416  }
417  }
418  }
419  layout.endLayout();
420 
421  //Update truncated
422  if (truncated != truncate) {
423  truncated = truncate;
424  emit q->truncatedChanged();
425  }
426  } else {
427  layout.beginLayout();
428  forever {
429  QTextLine line = layout.createLine();
430  if (!line.isValid())
431  break;
432  visibleCount++;
433  if (lineWidth)
434  line.setLineWidth(lineWidth);
435  }
436  layout.endLayout();
437  }
438 
439  qreal height = 0;
440  QRectF br;
441  for (int i = 0; i < layout.lineCount(); ++i) {
442  QTextLine line = layout.lineAt(i);
443  // set line spacing
444  line.setPosition(QPointF(line.position().x(), height));
445  if (elideText && i == layout.lineCount()-1) {
446  elidePos.setY(height + fm.ascent());
447  br = br.united(QRectF(elidePos, QSizeF(fm.width(elideChar), fm.ascent())));
448  }
449  br = br.united(line.naturalTextRect());
450  height += (lineHeightMode == QDeclarativeText::FixedHeight) ? lineHeight : line.height() * lineHeight;
451  }
452  br.setHeight(height);
453 
454  if (!q->widthValid())
455  naturalWidth = br.width();
456 
457  //Update the number of visible lines
458  if (lineCount != visibleCount) {
459  lineCount = visibleCount;
460  emit q->lineCountChanged();
461  }
462 
463  return QRect(qRound(br.x()), qRound(br.y()), qCeil(br.width()), qCeil(br.height()));
464 }
465 
471 {
472  //do layout
473  QSize size = layedOutTextRect.size();
474  //paint text
475  QPixmap img(size);
476  if (!size.isEmpty()) {
477  img.fill(Qt::transparent);
478 #ifdef Q_WS_MAC
479  bool oldSmooth = qt_applefontsmoothing_enabled;
481 #endif
482  QPainter p(&img);
483 #ifdef Q_WS_MAC
484  qt_applefontsmoothing_enabled = oldSmooth;
485 #endif
486  drawTextLayout(&p, QPointF(-layedOutTextRect.x(),0), drawStyle);
487  }
488  return img;
489 }
490 
495 void QDeclarativeTextPrivate::drawTextLayout(QPainter *painter, const QPointF &pos, bool drawStyle)
496 {
497  if (drawStyle)
498  painter->setPen(styleColor);
499  else
500  painter->setPen(color);
501  painter->setFont(font);
502  layout.draw(painter, pos);
503  if (!elidePos.isNull())
504  painter->drawText(pos + elidePos, elideChar);
505 }
506 
512 {
513  QSize size = doc->size().toSize();
514 
515  //paint text
516  QPixmap img(size);
517  img.fill(Qt::transparent);
518 #ifdef Q_WS_MAC
519  bool oldSmooth = qt_applefontsmoothing_enabled;
521 #endif
522  QPainter p(&img);
523 #ifdef Q_WS_MAC
524  qt_applefontsmoothing_enabled = oldSmooth;
525 #endif
526 
528 
529  QTextOption oldOption(doc->defaultTextOption());
530  if (drawStyle) {
531  context.palette.setColor(QPalette::Text, styleColor);
532  QTextOption colorOption(doc->defaultTextOption());
534  doc->setDefaultTextOption(colorOption);
535  } else {
536  context.palette.setColor(QPalette::Text, color);
537  }
538  doc->documentLayout()->draw(&p, context);
539  if (drawStyle)
540  doc->setDefaultTextOption(oldOption);
541  return img;
542 }
543 
548 {
550 
551  if(cacheAllTextAsImage || style != QDeclarativeText::Normal){//If actually using the image cache
552  if (imageCacheDirty)
553  return;
554 
555  imageCacheDirty = true;
556  imageCache = QPixmap();
557  }
558  if (q->isComponentComplete())
559  q->update();
560 }
561 
566 {
567  if (!imageCacheDirty)
568  return;
569 
570  if (text.isEmpty()) {
571 
572  imageCache = QPixmap();
573 
574  } else {
575 
576  QPixmap textImage;
577  QPixmap styledImage;
578 
579  if (richText) {
580  textImage = textDocumentImage(false);
581  if (style != QDeclarativeText::Normal)
582  styledImage = textDocumentImage(true); //### should use styleColor
583  } else {
584  textImage = textLayoutImage(false);
585  if (style != QDeclarativeText::Normal)
586  styledImage = textLayoutImage(true); //### should use styleColor
587  }
588 
589  switch (style) {
591  imageCache = drawOutline(textImage, styledImage);
592  break;
594  imageCache = drawOutline(textImage, styledImage, -1);
595  break;
597  imageCache = drawOutline(textImage, styledImage, 1);
598  break;
599  default:
600  imageCache = textImage;
601  break;
602  }
603 
604  }
605 
606  imageCacheDirty = false;
607 }
608 
613 {
614  if (!doc) {
616  doc = new QTextDocumentWithImageResources(q);
617  doc->setDocumentMargin(0);
618  }
619 }
620 
625 {
626  QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
627  img.fill(Qt::transparent);
628 
629  QPainter ppm(&img);
630 
631  QPoint pos(0, 0);
632  pos += QPoint(-1, 0);
633  ppm.drawPixmap(pos, styleSource);
634  pos += QPoint(2, 0);
635  ppm.drawPixmap(pos, styleSource);
636  pos += QPoint(-1, -1);
637  ppm.drawPixmap(pos, styleSource);
638  pos += QPoint(0, 2);
639  ppm.drawPixmap(pos, styleSource);
640 
641  pos += QPoint(0, -1);
642  ppm.drawPixmap(pos, source);
643  ppm.end();
644 
645  return img;
646 }
647 
651 QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset)
652 {
653  QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
654  img.fill(Qt::transparent);
655 
656  QPainter ppm(&img);
657 
658  ppm.drawPixmap(QPoint(0, yOffset), styleSource);
659  ppm.drawPixmap(0, 0, source);
660 
661  ppm.end();
662 
663  return img;
664 }
665 
714 {
715 }
716 
718 {
719 }
720 
907 {
908  Q_D(const QDeclarativeText);
909  return d->sourceFont;
910 }
911 
913 {
915  if (d->sourceFont == font)
916  return;
917 
918  d->sourceFont = font;
919  QFont oldFont = d->font;
920  d->font = font;
921  if (d->font.pointSizeF() != -1) {
922  // 0.5pt resolution
923  qreal size = qRound(d->font.pointSizeF()*2.0);
924  d->font.setPointSizeF(size/2.0);
925  }
926 
927  if (oldFont != d->font)
928  d->updateLayout();
929 
930  emit fontChanged(d->sourceFont);
931 }
932 
945 {
946  Q_D(const QDeclarativeText);
947  return d->text;
948 }
949 
951 {
953  if (d->text == n)
954  return;
955 
956  d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n));
957  d->text = n;
958  if (isComponentComplete()) {
959  if (d->richText) {
960  d->ensureDoc();
961  d->doc->setText(n);
962  d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
963  } else {
964  d->rightToLeftText = d->text.isRightToLeft();
965  }
966  d->determineHorizontalAlignment();
967  }
968  d->updateLayout();
969  emit textChanged(d->text);
970 }
971 
972 
998 {
999  Q_D(const QDeclarativeText);
1000  return d->color;
1001 }
1002 
1004 {
1006  if (d->color == color)
1007  return;
1008 
1009  d->color = color;
1010  d->invalidateImageCache();
1011  emit colorChanged(d->color);
1012 }
1013 
1042 {
1043  Q_D(const QDeclarativeText);
1044  return d->style;
1045 }
1046 
1048 {
1050  if (d->style == style)
1051  return;
1052 
1053  // changing to/from Normal requires the boundingRect() to change
1054  if (isComponentComplete() && (d->style == Normal || style == Normal))
1056  d->style = style;
1057  d->invalidateImageCache();
1058  emit styleChanged(d->style);
1059 }
1060 
1080 {
1081  Q_D(const QDeclarativeText);
1082  return d->styleColor;
1083 }
1084 
1086 {
1088  if (d->styleColor == color)
1089  return;
1090 
1091  d->styleColor = color;
1092  d->invalidateImageCache();
1093  emit styleColorChanged(d->styleColor);
1094 }
1095 
1096 
1124 {
1125  Q_D(const QDeclarativeText);
1126  return d->hAlign;
1127 }
1128 
1130 {
1132  bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
1133  d->hAlignImplicit = false;
1134  if (d->setHAlign(align, forceAlign) && isComponentComplete())
1135  d->updateLayout();
1136 }
1137 
1139 {
1141  d->hAlignImplicit = true;
1142  if (d->determineHorizontalAlignment() && isComponentComplete())
1143  d->updateLayout();
1144 }
1145 
1147 {
1148  Q_D(const QDeclarativeText);
1149  QDeclarativeText::HAlignment effectiveAlignment = d->hAlign;
1150  if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
1151  switch (d->hAlign) {
1153  effectiveAlignment = QDeclarativeText::AlignRight;
1154  break;
1156  effectiveAlignment = QDeclarativeText::AlignLeft;
1157  break;
1158  default:
1159  break;
1160  }
1161  }
1162  return effectiveAlignment;
1163 }
1164 
1166 {
1168  if (hAlign != alignment || forceAlign) {
1169  hAlign = alignment;
1170  emit q->horizontalAlignmentChanged(hAlign);
1171  return true;
1172  }
1173  return false;
1174 }
1175 
1177 {
1179  if (hAlignImplicit && q->isComponentComplete()) {
1180  bool alignToRight = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : rightToLeftText;
1182  }
1183  return false;
1184 }
1185 
1187 {
1189  if (q->isComponentComplete()) {
1190  if (!hAlignImplicit && (hAlign == QDeclarativeText::AlignRight || hAlign == QDeclarativeText::AlignLeft)) {
1191  updateLayout();
1192  }
1193  }
1194 }
1195 
1197 {
1198  return doc;
1199 }
1200 
1202 {
1203  Q_D(const QDeclarativeText);
1204  return d->vAlign;
1205 }
1206 
1208 {
1210  if (d->vAlign == align)
1211  return;
1212 
1213  if (isComponentComplete())
1215  d->vAlign = align;
1217 }
1218 
1236 {
1237  Q_D(const QDeclarativeText);
1238  return d->wrapMode;
1239 }
1240 
1242 {
1244  if (mode == d->wrapMode)
1245  return;
1246 
1247  d->wrapMode = mode;
1248  d->updateLayout();
1249 
1251 }
1252 
1266 int QDeclarativeText::lineCount() const
1267 {
1268  Q_D(const QDeclarativeText);
1269  return d->lineCount;
1270 }
1271 
1286 bool QDeclarativeText::truncated() const
1287 {
1288  Q_D(const QDeclarativeText);
1289  return d->truncated;
1290 }
1291 
1308 {
1309  Q_D(const QDeclarativeText);
1310  return d->maximumLineCount;
1311 }
1312 
1314 {
1316 
1317  d->maximumLineCountValid = lines==INT_MAX ? false : true;
1318  if (d->maximumLineCount != lines) {
1319  d->maximumLineCount = lines;
1320  d->updateLayout();
1322  }
1323 }
1324 
1326 {
1329  d->elidePos = QPointF();
1330  if (d->truncated != false) {
1331  d->truncated = false;
1333  }
1334 }
1335 
1394 {
1395  Q_D(const QDeclarativeText);
1396  return d->format;
1397 }
1398 
1400 {
1402  if (format == d->format)
1403  return;
1404  d->format = format;
1405  bool wasRich = d->richText;
1406  d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
1407 
1408  if (!wasRich && d->richText && isComponentComplete()) {
1409  d->ensureDoc();
1410  d->doc->setText(d->text);
1411  }
1412 
1413  d->updateLayout();
1414 
1415  emit textFormatChanged(d->format);
1416 }
1417 
1447 {
1448  Q_D(const QDeclarativeText);
1449  return d->elideMode;
1450 }
1451 
1453 {
1455  if (mode == d->elideMode)
1456  return;
1457 
1458  d->elideMode = mode;
1459  d->updateLayout();
1460 
1461  emit elideModeChanged(d->elideMode);
1462 }
1463 
1466 {
1467  Q_D(const QDeclarativeText);
1468 
1469  QRect rect = d->layedOutTextRect;
1470  if (d->style != Normal)
1471  rect.adjust(-1, 0, 1, 2);
1472 
1473  // Could include font max left/right bearings to either side of rectangle.
1474 
1475  int h = height();
1476  switch (d->vAlign) {
1477  case AlignTop:
1478  break;
1479  case AlignBottom:
1480  rect.moveTop(h - rect.height());
1481  break;
1482  case AlignVCenter:
1483  rect.moveTop((h - rect.height()) / 2);
1484  break;
1485  }
1486 
1487  return QRectF(rect);
1488 }
1489 
1491 void QDeclarativeText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
1492 {
1494  if ((!d->internalWidthUpdate && newGeometry.width() != oldGeometry.width())
1495  && (d->wrapMode != QDeclarativeText::NoWrap
1496  || d->elideMode != QDeclarativeText::ElideNone
1497  || d->hAlign != QDeclarativeText::AlignLeft)) {
1498  if ((d->singleline || d->maximumLineCountValid) && d->elideMode != QDeclarativeText::ElideNone && widthValid()) {
1499  // We need to re-elide
1500  d->updateLayout();
1501  } else {
1502  // We just need to re-layout
1503  d->updateSize();
1504  }
1505  }
1506 
1507  QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
1508 }
1509 
1520 {
1521  Q_D(const QDeclarativeText);
1522  return d->paintedSize.width();
1523 }
1524 
1535 {
1536  Q_D(const QDeclarativeText);
1537  return d->paintedSize.height();
1538 }
1539 
1554 {
1555  Q_D(const QDeclarativeText);
1556  return d->lineHeight;
1557 }
1558 
1560 {
1562 
1563  if ((d->lineHeight == lineHeight) || (lineHeight < 0.0))
1564  return;
1565 
1566  d->lineHeight = lineHeight;
1567  d->updateLayout();
1568  emit lineHeightChanged(lineHeight);
1569 }
1570 
1587 {
1588  Q_D(const QDeclarativeText);
1589  return d->lineHeightMode;
1590 }
1591 
1593 {
1595  if (mode == d->lineHeightMode)
1596  return;
1597 
1598  d->lineHeightMode = mode;
1599  d->updateLayout();
1600 
1602 }
1603 
1608 {
1609  Q_D(const QDeclarativeText);
1610  return d->doc ? d->doc->resourcesLoading() : 0;
1611 }
1612 
1615 {
1617 
1618  if (d->cacheAllTextAsImage || d->style != Normal) {
1619  d->checkImageCache();
1620  if (d->imageCache.isNull())
1621  return;
1622 
1623  bool oldAA = p->testRenderHint(QPainter::Antialiasing);
1624  bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
1625  if (d->smooth)
1627 
1628  QRect br = boundingRect().toRect();
1629 
1630  bool needClip = clip() && (d->imageCache.width() > width() ||
1631  d->imageCache.height() > height());
1632 
1633  if (needClip)
1634  p->drawPixmap(0, 0, width(), height(), d->imageCache, -br.x(), -br.y(), width(), height());
1635  else
1636  p->drawPixmap(br.x(), br.y(), d->imageCache);
1637 
1638  if (d->smooth) {
1641  }
1642  } else {
1643  QRectF bounds = boundingRect();
1644 
1645  bool needClip = clip() && (d->layedOutTextRect.width() > width() ||
1646  d->layedOutTextRect.height() > height());
1647 
1648  if (needClip) {
1649  p->save();
1650  p->setClipRect(0, 0, width(), height(), Qt::IntersectClip);
1651  }
1652  if (d->richText) {
1654  context.palette.setColor(QPalette::Text, d->color);
1655  p->translate(bounds.x(), bounds.y());
1656  d->doc->documentLayout()->draw(p, context);
1657  p->translate(-bounds.x(), -bounds.y());
1658  } else {
1659  d->drawTextLayout(p, QPointF(0, bounds.y()), false);
1660  }
1661 
1662  if (needClip) {
1663  p->restore();
1664  }
1665  }
1666 }
1667 
1670 {
1673  if (d->updateOnComponentComplete) {
1674  d->updateOnComponentComplete = false;
1675  if (d->richText) {
1676  d->ensureDoc();
1677  d->doc->setText(d->text);
1678  d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
1679  } else {
1680  d->rightToLeftText = d->text.isRightToLeft();
1681  }
1682  d->determineHorizontalAlignment();
1683  d->updateLayout();
1684  }
1685 }
1686 
1689 {
1691 
1692  if (!d->richText || !d->doc || d->doc->documentLayout()->anchorAt(event->pos()).isEmpty()) {
1693  event->setAccepted(false);
1694  d->activeLink.clear();
1695  } else {
1696  d->activeLink = d->doc->documentLayout()->anchorAt(event->pos());
1697  }
1698 
1699  // ### may malfunction if two of the same links are clicked & dragged onto each other)
1700 
1701  if (!event->isAccepted())
1703 
1704 }
1705 
1708 {
1710 
1711  // ### confirm the link, and send a signal out
1712  if (d->richText && d->doc && d->activeLink == d->doc->documentLayout()->anchorAt(event->pos()))
1713  emit linkActivated(d->activeLink);
1714  else
1715  event->setAccepted(false);
1716 
1717  if (!event->isAccepted())
1719 }
1720 
1722 
1723 #include "qdeclarativetext.moc"
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
void setColor(const QColor &c)
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
double d
Definition: qnumeric_p.h:62
TextFormat textFormat() const
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
QGraphicsItem * parent
qreal right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:527
unsigned int QRgb
Definition: qrgb.h:53
int type
Definition: qmetatype.cpp:239
double qreal
Definition: qglobal.h:1193
QPixmap textLayoutImage(bool drawStyle)
Returns a painted version of the QDeclarativeTextPrivate::layout QTextLayout.
void setHeight(qreal h)
Sets the height of the rectangle to the given height.
Definition: qrect.h:787
The QFontMetrics class provides font metrics information.
Definition: qfontmetrics.h:65
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static void parse(const QString &string, QTextLayout &layout)
int lineCount() const
Returns the number of lines of this document (if the layout supports this).
void setPosition(const QPointF &pos)
Moves the line to position pos.
int width() const
Returns the width of the pixmap.
Definition: qpixmap.cpp:630
QDeclarativeParserStatus ** d
void clear()
Removes all items from the hash.
Definition: qhash.h:574
TextElideMode elideMode() const
QHash< QUrl, QDeclarativePixmap * > m_resources
void colorChanged(const QColor &color)
void setText(const QString &)
int qCeil(qreal v)
Definition: qmath.h:63
Q_GUI_EXPORT bool qt_applefontsmoothing_enabled
LineHeightMode lineHeightMode() const
bool widthValid() const
Returns whether the width property has been set explicitly.
QSize toSize() const
Returns an integer based copy of this size.
Definition: qsize.h:355
bool isComponentComplete() const
Returns true if construction of the QML component is complete; otherwise returns false.
QRectF boundingRect() const
DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE)
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
void setElideMode(TextElideMode)
virtual bool event(QEvent *)
void setWrapMode(WrapMode w)
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
QSizeF size() const
void setClipRect(const QRectF &, Qt::ClipOperation op=Qt::ReplaceClip)
Enables clipping, and sets the clip region to the given rectangle using the given clip operation...
Definition: qpainter.cpp:2801
#define SLOT(a)
Definition: qobjectdefs.h:226
TextElideMode
Definition: qnamespace.h:263
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
Definition: qgraphicsitem.h:89
The QGraphicsSceneMouseEvent class provides mouse events in the graphics view framework.
qreal left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:525
The QTextLine class represents a line of text inside a QTextLayout.
Definition: qtextlayout.h:197
void restore()
Restores the current painter state (pops a saved state off the stack).
Definition: qpainter.cpp:1620
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
WrapMode
This enum describes how text is wrapped in a document.
Definition: qtextoption.h:102
int textLength() const
Returns the length of the text in the line.
QUrl resolvedUrl(const QUrl &)
Resolves the URL src relative to the URL of the containing component.
Q_GUI_EXPORT bool mightBeRichText(const QString &)
Returns true if the string text is likely to be rich text; otherwise returns false.
void styleChanged(TextStyle style)
void lineHeightChanged(qreal lineHeight)
void fontChanged(const QFont &font)
bool truncated() const
qreal paintedWidth() const
void setLineWidth(qreal width)
Lays out the line with the given width.
QColor color() const
void setFlags(Flags flags)
Sets the flags associated with the option to the given flags.
Definition: qtextoption.h:151
static QRectF setupTextLayout(QTextLayout *layout)
bool testRenderHint(RenderHint hint) const
Returns true if hint is set; otherwise returns false.
Definition: qpainter.h:457
WrapMode wrapMode() const
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
void truncatedChanged()
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
VAlignment vAlign() const
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event event, can be reimplemented to receive mouse press events for this item...
qreal paintedHeight() const
void setTextFormat(TextFormat format)
QPalette palette
the default color that is used for the text, when no color is specified.
void textFormatChanged(TextFormat textFormat)
Q_DECLARATIVE_EXPORT QDeclarativeContext * qmlContext(const QObject *)
void invalidateImageCache()
Mark the image cache as dirty.
#define Q_D(Class)
Definition: qglobal.h:2482
bool isValid() const
Returns true if this text line is valid; otherwise returns false.
Definition: qtextlayout.h:201
The QSizeF class defines the size of a two-dimensional object using floating point precision...
Definition: qsize.h:202
TextStyle style() const
void save()
Saves the current painter state (pushes the state onto a stack).
Definition: qpainter.cpp:1590
QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags=0) const
If the string text is wider than width, returns an elided version of the string (i.
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
#define Q_Q(Class)
Definition: qglobal.h:2483
static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource)
Draw styleSource as an outline around source and return the new image.
int ascent() const
Returns the ascent of the font.
void setPlainText(const QString &text)
Replaces the entire contents of the document with the given plain text.
int width() const
Returns the width.
Definition: qsize.h:126
int lineCount() const
void setAlignment(Qt::Alignment alignment)
Sets the option&#39;s text alignment to the specified alignment.
Definition: qtextoption.h:148
void drawText(const QPointF &p, const QString &s)
Draws the given text with the currently defined text direction, beginning at the given position...
Definition: qpainter.cpp:6231
void setRenderHint(RenderHint hint, bool on=true)
Sets the given render hint on the painter if on is true; otherwise clears the render hint...
Definition: qpainter.cpp:7620
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
bool isAccepted() const
Definition: qcoreevent.h:307
const QPixmap & pixmap() const
static bool isEmpty(const char *str)
The QDeclarativeItem class provides the most basic of all visual items in QML.
bool contains(const T &value) const
Definition: qset.h:91
QTextDocumentWithImageResources(QDeclarativeText *parent)
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
void checkImageCache()
Tests if the image cache is dirty, and repaints it if it is.
void linkActivated(const QString &link)
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
const char * name
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
#define emit
Definition: qobjectdefs.h:76
QPixmap textDocumentImage(bool drawStyle)
Returns a painted version of the QDeclarativeTextPrivate::doc QTextDocument.
const char * layout
void adjust(int x1, int y1, int x2, int y2)
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition: qrect.h:434
virtual QVariant loadResource(int type, const QUrl &name)
Loads data of the specified type from the resource with the given name.
bool isEmpty() const
Returns true if the hash contains no items; otherwise returns false.
Definition: qhash.h:297
const_iterator insert(const T &value)
Definition: qset.h:179
bool clip() const
QColor styleColor() const
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
virtual void componentComplete()
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
void setHtml(const QString &html)
Replaces the entire contents of the document with the given HTML-formatted text in the html string...
void elideModeChanged(TextElideMode mode)
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
This function is called to handle this item&#39;s changes in geometry from oldGeometry to newGeometry...
QRect toRect() const
Returns a QRect based on the values of this rectangle.
Definition: qrect.h:845
void mousePressEvent(QGraphicsSceneMouseEvent *event)
#define Q_OBJECT
Definition: qobjectdefs.h:157
void setMaximumLineCount(int lines)
void setLineHeightMode(LineHeightMode)
void setHAlign(HAlignment align)
QFont font() const
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition: qpixmap.cpp:1080
QPointF position() const
Returns the line&#39;s position relative to the text layout&#39;s position.
void setRenderHints(RenderHints hints, bool on=true)
Sets the given render hints on the painter if on is true; otherwise clears the render hints...
Definition: qpainter.cpp:7649
QTextDocument * textDocument()
QVariant loadResource(int type, const QUrl &name)
Loads data of the specified type from the resource with the given name.
void setStyle(TextStyle style)
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the hash...
Definition: qhash.h:467
void prepareGeometryChange()
Prepares the item for a geometry change.
bool connectFinished(QObject *, const char *)
The QFont class specifies a font used for drawing text.
Definition: qfont.h:64
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
void drawTextLayout(QPainter *p, const QPointF &pos, bool drawStyle)
Paints the QDeclarativeTextPrivate::layout QTextLayout into painter at pos.
qreal x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:664
QString text() const
HAlignment effectiveHAlign() const
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
qreal lineHeight() const
virtual void componentComplete()
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
void setColor(ColorGroup cg, ColorRole cr, const QColor &color)
Sets the color in the specified color group, used for the given color role, to the specified solid co...
Definition: qpalette.h:201
QRectF united(const QRectF &other) const
Returns the bounding rectangle of this rectangle and the given rectangle.
Definition: qrect.h:828
The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash.
Definition: qhash.h:330
The QAbstractTextDocumentLayout::PaintContext class is a convenience class defining the parameters us...
void setPen(const QColor &color)
Sets the painter&#39;s pen to have style Qt::SolidLine, width 0 and the specified color.
Definition: qpainter.cpp:4047
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
bool setHAlign(QDeclarativeText::HAlignment, bool forceAlign=false)
The QTextOption class provides a description of general rich text properties.
Definition: qtextoption.h:59
The QDeclarativeContext class defines a context within a QML engine.
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
QDeclarativeEngine * engine() const
Return the context&#39;s QDeclarativeEngine, or 0 if the context has no QDeclarativeEngine or the QDeclar...
virtual qreal implicitWidth() const
The QTextDocument class holds formatted text that can be viewed and edited using a QTextEdit...
QPointF pos() const
Returns the mouse cursor position in item coordinates.
void setFont(const QFont &font)
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device...
Definition: qpainter.cpp:5619
int height() const
Returns the height of the pixmap.
Definition: qpixmap.cpp:645
static QDeclarativeTextPrivate * get(QDeclarativeText *t)
HAlignment hAlign() const
void setWrapMode(WrapMode wrap)
Sets the option&#39;s text wrap mode to the given mode.
Definition: qtextoption.h:109
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
void setFont(const QFont &f)
Sets the painter&#39;s font to the given font.
Definition: qpainter.cpp:4288
int resourcesLoading() const
Returns the number of resources (images) that are being loaded asynchronously.
void setVAlign(VAlignment align)
QDeclarativeText(QDeclarativeItem *parent=0)
void setLineHeight(qreal lineHeight)
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
Definition: qhash.h:865
void textChanged(const QString &text)
void maximumLineCountChanged()
void moveTop(int pos)
Moves the rectangle vertically, leaving the rectangle&#39;s top edge at the given y coordinate.
Definition: qrect.h:353
void lineHeightModeChanged(LineHeightMode mode)
bool isEmpty() const
Returns true if either of the width and height is less than or equal to 0; otherwise returns false...
Definition: qsize.h:120
void verticalAlignmentChanged(VAlignment alignment)
QDeclarativeInfo qmlInfo(const QObject *me)
#define slots
Definition: qobjectdefs.h:68
static Qt::LayoutDirection keyboardInputDirection()
Returns the current keyboard input direction.
int height() const
Returns the height of the font.
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
int maximumLineCount() const
void styleColorChanged(const QColor &color)
The QStyleOptionGraphicsItem class is used to describe the parameters needed to draw a QGraphicsItem...
Definition: qstyleoption.h:867
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
void ensureDoc()
Ensures the QDeclarativeTextPrivate::doc variable is set to a valid text document.
#define INT_MAX
qreal height() const
Returns the line&#39;s height.
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event event, can be reimplemented to receive mouse release events for this it...
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
void wrapModeChanged()
bool end()
Ends painting.
Definition: qpainter.cpp:1929
int textStart() const
Returns the start of the line from the beginning of the string passed to the QTextLayout.
#define text
Definition: qobjectdefs.h:80
void setStyleColor(const QColor &c)
QRectF naturalTextRect() const
Returns the rectangle covered by the line.
QRect setupTextLayout()
Lays out the QDeclarativeTextPrivate::layout QTextLayout in the constraints of the QDeclarativeText...
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
Definition: qpainter.cpp:3311
#define forever
This macro is provided for convenience for writing infinite loops.
Definition: qglobal.h:2452