35 #include <QPainter> |
35 #include <QPainter> |
36 #include <QTextOption> |
36 #include <QTextOption> |
37 #include <QApplication> |
37 #include <QApplication> |
38 |
38 |
39 #ifdef HB_TEXT_MEASUREMENT_UTILITY |
39 #ifdef HB_TEXT_MEASUREMENT_UTILITY |
40 #include "hbtextmeasurementutility_p.h" |
40 #include "hbtextmeasurementutility_r.h" |
41 #include "hbfeaturemanager_r.h" |
41 #include "hbtextmeasurementutility_r_p.h" |
42 #endif |
42 #endif |
43 |
43 |
44 // #define HB_TEXT_ITEM_LOGS |
|
45 #define EPSILON 0.01 |
44 #define EPSILON 0.01 |
46 |
45 |
47 #ifdef HB_TEXT_ITEM_LOGS |
46 // #define HB_DEBUG_TEXT_ITEM_LOGS |
48 # include <QDebug> |
47 #ifdef HB_DEBUG_TEXT_ITEM_LOGS |
49 const int KMaxLogedTextLength = 30; |
48 #include <QDebug> |
50 #endif // HB_TEXT_ITEM_LOGS |
49 |
|
50 #define HB_TEXT_ITEM_LOG(args) qDebug() << "HbTextItem::" << __FUNCTION__ \ |
|
51 << "(" << __LINE__ << ")"\ |
|
52 << ", objectName:" << this->objectName() \ |
|
53 << ", text: " << this->text().left(30) \ |
|
54 << " " << args; |
|
55 #define HB_TEXT_ITEM_PRIV_LOG(args) qDebug() << "HbTextItemPrivate::" << __FUNCTION__ \ |
|
56 << "(" << __LINE__ << ")"\ |
|
57 << ", objectName:" << q_ptr->objectName() \ |
|
58 << ", text: " << this->mText.left(30) \ |
|
59 << " " << args; |
|
60 #else |
|
61 #define HB_TEXT_ITEM_LOG(args) |
|
62 #define HB_TEXT_ITEM_PRIV_LOG(args) |
|
63 #endif // HB_DEBUG_TEXT_ITEM_LOGS |
51 |
64 |
52 bool HbTextItemPrivate::outlinesEnabled = false; |
65 bool HbTextItemPrivate::outlinesEnabled = false; |
53 |
66 |
54 static const QString KDefaultColorThemeName = "qtc_view_normal"; |
67 static const QString KDefaultColorThemeName = "qtc_view_normal"; |
55 const qreal MinimumWidth = 5.0; // minimum width if there is some text. |
68 const qreal MinimumWidth = 5.0; // minimum width if there is some text. |
67 mMinLines(1), |
80 mMinLines(1), |
68 mMaxLines(0), |
81 mMaxLines(0), |
69 mMinWidthForAdjust(-1), |
82 mMinWidthForAdjust(-1), |
70 mMaxWidthForAdjust(-1), |
83 mMaxWidthForAdjust(-1), |
71 mDefaultHeight(-1), |
84 mDefaultHeight(-1), |
|
85 mHasMultiTrans(false), |
72 mUpdateColor(true), |
86 mUpdateColor(true), |
73 mEventPosted(false) |
87 mEventPosted(false), |
|
88 inConstructor(1) |
74 { |
89 { |
75 } |
90 } |
76 |
91 |
77 void HbTextItemPrivate::init(QGraphicsItem *) |
92 void HbTextItemPrivate::init(QGraphicsItem *) |
78 { |
93 { |
79 Q_Q(HbTextItem); |
94 Q_Q(HbTextItem); |
80 |
95 inConstructor = 1; |
81 q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); |
96 q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); |
82 q->setFlag(QGraphicsItem::ItemClipsToShape, false); |
97 q->setFlag(QGraphicsItem::ItemClipsToShape, false); |
83 q->setFlag(QGraphicsItem::ItemIsSelectable, false); |
98 q->setFlag(QGraphicsItem::ItemIsSelectable, false); |
84 q->setFlag(QGraphicsItem::ItemIsFocusable, false); |
99 q->setFlag(QGraphicsItem::ItemIsFocusable, false); |
85 |
100 |
86 QTextOption textOption = mTextLayout.textOption(); |
101 QTextOption textOption = mTextLayout.textOption(); |
87 textOption.setWrapMode(QTextOption::WordWrap); |
102 textOption.setWrapMode(QTextOption::WordWrap); |
88 mTextLayout.setTextOption(textOption); |
103 mTextLayout.setTextOption(textOption); |
89 mTextLayout.setCacheEnabled(true); |
104 mTextLayout.setCacheEnabled(true); |
90 mTextLayout.setFont(q->font()); |
105 mTextLayout.setFont(q->font()); |
|
106 inConstructor = 0; |
91 } |
107 } |
92 |
108 |
93 void HbTextItemPrivate::clear() |
109 void HbTextItemPrivate::clear() |
94 { |
110 { |
95 // no implementation needed |
111 // no implementation needed |
134 if(tempText.indexOf('\n')>=0) { |
150 if(tempText.indexOf('\n')>=0) { |
135 // to prevent creation of deep copy if replace has no effect |
151 // to prevent creation of deep copy if replace has no effect |
136 tempText.replace('\n', QChar::LineSeparator); |
152 tempText.replace('\n', QChar::LineSeparator); |
137 } |
153 } |
138 |
154 |
139 // Need to call elidedText explicitly to enable multiple length translations. |
155 // Need to call elidedText explicitly to enable multiple length translations. |
140 tempText = fontMetrics.elidedText(tempText, Qt::ElideNone, lineWidth); |
156 tempText = fontMetrics.elidedText(tempText, Qt::ElideNone, lineWidth); |
141 bool textTruncated = doLayout(tempText, lineWidth, fontMetrics.lineSpacing()); |
157 bool textTruncated = doLayout(tempText, lineWidth, fontMetrics.lineSpacing()); |
142 |
158 |
143 if(mElideMode!=Qt::ElideNone && !tempText.isEmpty()) { |
159 if(mElideMode!=Qt::ElideNone && !tempText.isEmpty()) { |
144 if( ( mTextLayout.boundingRect().height() - newSize.height() > EPSILON ) || |
160 if( ( mTextLayout.boundingRect().height() - newSize.height() > EPSILON ) || |
150 fontMetrics.lineSpacing()); |
166 fontMetrics.lineSpacing()); |
151 } |
167 } |
152 } |
168 } |
153 |
169 |
154 calculateVerticalOffset(); |
170 calculateVerticalOffset(); |
|
171 mBoundingRect = layoutBoundingRect(); |
155 calculateFadeRects(); |
172 calculateFadeRects(); |
156 |
173 |
157 // build of text layout is completed |
174 // build of text layout is completed |
158 mInvalidateShownText = false; |
175 mInvalidateShownText = false; |
159 } |
176 } |
215 if(!elidedText.isEmpty() && !elidedText.endsWith(QChar::LineSeparator)) { |
232 if(!elidedText.isEmpty() && !elidedText.endsWith(QChar::LineSeparator)) { |
216 // needed to prevent to move "..." to line before last line |
233 // needed to prevent to move "..." to line before last line |
217 elidedText.append(QChar::LineSeparator); |
234 elidedText.append(QChar::LineSeparator); |
218 } |
235 } |
219 |
236 |
220 int n = lastLine.textLength(); |
237 int n = lastLine.textLength()-1; |
221 if(textToElide.at(lastLine.textStart()+n-1)!=QChar::LineSeparator) { |
238 if(textToElide.at(lastLine.textStart()+n)!=QChar::LineSeparator) { |
222 n = -1; |
239 n = -1; |
223 } |
240 } |
224 elidedText.append(metrics.elidedText(textToElide.mid(lastLine.textStart(), n), |
241 elidedText.append(metrics.elidedText(textToElide.mid(lastLine.textStart(), n), |
225 mElideMode, size.width(),textFlagsFromTextOption())); |
242 mElideMode, size.width(),textFlagsFromTextOption())); |
226 |
243 |
301 bool HbTextItemPrivate::isAdjustHightNeeded(qreal newWidth, |
318 bool HbTextItemPrivate::isAdjustHightNeeded(qreal newWidth, |
302 qreal prefHeight, |
319 qreal prefHeight, |
303 qreal minHeight, |
320 qreal minHeight, |
304 qreal maxHeight) |
321 qreal maxHeight) |
305 { |
322 { |
306 #ifdef HB_TEXT_ITEM_LOGS |
|
307 qDebug() << "isAdjustHightNeeded for: " << q_ptr->objectName() |
|
308 << " text=" << mText.left(KMaxLogedTextLength) |
|
309 << " adjusted=" << mAdjustedSize |
|
310 << " prefHeight=" << prefHeight |
|
311 << " minHeight=" << minHeight |
|
312 << " lastConstraint=" << mLastConstraint |
|
313 << " " << mTextLayout.font(); |
|
314 #endif // HB_TEXT_ITEM_LOGS |
|
315 |
|
316 // first check if wrapping of text is not active |
323 // first check if wrapping of text is not active |
317 QTextOption::WrapMode wrapMode = mTextLayout.textOption().wrapMode(); |
324 QTextOption::WrapMode wrapMode = mTextLayout.textOption().wrapMode(); |
318 if (wrapMode==QTextOption::NoWrap |
325 if (wrapMode==QTextOption::NoWrap |
319 || wrapMode==QTextOption::ManualWrap) { |
326 || wrapMode==QTextOption::ManualWrap) { |
320 return false; |
327 return false; |
327 |
334 |
328 // check if line count is fixed |
335 // check if line count is fixed |
329 if (mMaxLines == mMinLines) { |
336 if (mMaxLines == mMinLines) { |
330 return false; |
337 return false; |
331 } |
338 } |
|
339 |
|
340 HB_TEXT_ITEM_PRIV_LOG("adjusted=" << mAdjustedSize |
|
341 << " prefHeight=" << prefHeight |
|
342 << " minHeight=" << minHeight |
|
343 << " lastConstraint=" << mLastConstraint |
|
344 << " " << mTextLayout.font()) |
332 |
345 |
333 // check if adjusted size has been already calculated |
346 // check if adjusted size has been already calculated |
334 // new width is bigger then last estimated range of same height |
347 // new width is bigger then last estimated range of same height |
335 if ((mMaxWidthForAdjust>=newWidth |
348 if ((mMaxWidthForAdjust>=newWidth |
336 // new width is smaller then last estimated range of same height |
349 // new width is smaller then last estimated range of same height |
345 } |
358 } |
346 |
359 |
347 // if preconditions are met test if current hight is enough |
360 // if preconditions are met test if current hight is enough |
348 const QFontMetricsF metrics(mTextLayout.font()); |
361 const QFontMetricsF metrics(mTextLayout.font()); |
349 |
362 |
|
363 QString txt(mText); |
|
364 if (mHasMultiTrans) { |
|
365 // it has to be like that since same aproach is used in rebuildTextLayout |
|
366 // so to be consistent is sizeHInt and what is shown this has to be done |
|
367 txt = metrics.elidedText(mText, Qt::ElideNone, newWidth); |
|
368 } |
350 // heavy calculation: check if text fits in current size and cache result |
369 // heavy calculation: check if text fits in current size and cache result |
351 QSizeF newAdjust = metrics.boundingRect(QRectF(0, 0, newWidth, QWIDGETSIZE_MAX), |
370 QSizeF newAdjust = metrics.boundingRect(QRectF(0, 0, newWidth, QWIDGETSIZE_MAX), |
352 textFlagsFromTextOption(), |
371 textFlagsFromTextOption(), |
353 mText).size(); |
372 txt).size(); |
354 |
373 |
355 if (qFuzzyCompare(newAdjust.height(), mAdjustedSize.height())) { |
374 if (qFuzzyCompare(newAdjust.height(), mAdjustedSize.height())) { |
356 // height is same as last time update range of same height |
375 // height is same as last time update range of same height |
357 mMaxWidthForAdjust = qMax(mMaxWidthForAdjust, newWidth); |
376 mMaxWidthForAdjust = qMax(mMaxWidthForAdjust, newWidth); |
358 mMinWidthForAdjust = qMin(mMinWidthForAdjust, newWidth); |
377 mMinWidthForAdjust = qMin(mMinWidthForAdjust, newWidth); |
383 |
402 |
384 // all conditions for calling updateGeometry are meet |
403 // all conditions for calling updateGeometry are meet |
385 return true; |
404 return true; |
386 } |
405 } |
387 |
406 |
|
407 bool HbTextItemPrivate::isAdjustWidthNeeded(qreal newWidth) |
|
408 { |
|
409 if (!mHasMultiTrans) { |
|
410 return false; |
|
411 } |
|
412 |
|
413 if (mLastConstraint.width()>0) { |
|
414 return false; |
|
415 } // check if adjusted size has been already calculated |
|
416 // new width is bigger then last estimated range of same height |
|
417 |
|
418 if (!mAdjustedSize.isValid()) { |
|
419 // this means that preferred size is set outside of class by setPreferredSize |
|
420 // so sizeHint(Qt::Preferredsize) was not called and size adjustment is useless |
|
421 return false; |
|
422 } |
|
423 |
|
424 HB_TEXT_ITEM_PRIV_LOG("oldadjusted=" << mAdjustedSize |
|
425 << " newWidth=" << newWidth |
|
426 << " lastConstraint=" << mLastConstraint) |
|
427 |
|
428 if ((mMaxWidthForAdjust>=newWidth |
|
429 // new width is smaller then last estimated range of same height |
|
430 && newWidth>=mMinWidthForAdjust)) { |
|
431 return false; |
|
432 } |
|
433 |
|
434 QFontMetricsF metrics(q_ptr->font()); |
|
435 |
|
436 // heavy calculation: check if text fits in current size and cache result |
|
437 // note that no wrapping is used here since full width of text is needed to return |
|
438 // proper preferred sizeHint |
|
439 QSizeF newAdjust = metrics.boundingRect(QRectF(0, 0, newWidth, QWIDGETSIZE_MAX), |
|
440 0, |
|
441 mText).size(); |
|
442 |
|
443 if (qFuzzyCompare(newAdjust.width(), mAdjustedSize.width())) { |
|
444 return false; |
|
445 } |
|
446 |
|
447 if (mAdjustedSize.width()<newAdjust.width() |
|
448 && newAdjust.width()>newWidth) { |
|
449 qWarning("Provided multiple translation: \"%s\", " |
|
450 "has wrong order of possible translations. " |
|
451 "This could lead to infinitive loop of LayoutRequest events.", |
|
452 mText.toLatin1().data()); |
|
453 |
|
454 return false; |
|
455 } |
|
456 mAdjustedSize = newAdjust; |
|
457 |
|
458 mMaxWidthForAdjust = mMinWidthForAdjust = newAdjust.width(); |
|
459 // it must be like this since it is unknown if there will be next resize or not |
|
460 // size hint width is changed so change of width can occur and wrapping can be active |
|
461 |
|
462 HB_TEXT_ITEM_PRIV_LOG("newAdjusted=" << mAdjustedSize |
|
463 << " newWidth=" << newWidth) |
|
464 |
|
465 return true; |
|
466 } |
|
467 |
388 void HbTextItemPrivate::clearAdjustedSizeCache() |
468 void HbTextItemPrivate::clearAdjustedSizeCache() |
389 { |
469 { |
390 // clear cache of size |
470 // clear cache of size |
391 mMinWidthForAdjust = -1; |
471 mMinWidthForAdjust = -1; |
392 mMaxWidthForAdjust = -1; |
472 mMaxWidthForAdjust = -1; |
400 if (mAdjustedSize.isValid() && constraint == mLastConstraint) { |
480 if (mAdjustedSize.isValid() && constraint == mLastConstraint) { |
401 // return cached value, see more in: |
481 // return cached value, see more in: |
402 // - HbTextItemPrivate::isAdjustHightNeeded |
482 // - HbTextItemPrivate::isAdjustHightNeeded |
403 // - HbTextItem::resizeEvent |
483 // - HbTextItem::resizeEvent |
404 |
484 |
405 #ifdef HB_TEXT_ITEM_LOGS |
485 HB_TEXT_ITEM_PRIV_LOG("mAdjustedSize: " << mAdjustedSize |
406 qDebug() << "HbTextItemPrivate::calculatePrefferedSize: returning cached value: " << mAdjustedSize |
486 << " font:" << mTextLayout.font()) |
407 << " font:" << mTextLayout.font() |
487 |
408 << " text:" << mText.left(KMaxLogedTextLength); |
|
409 #endif |
|
410 return mAdjustedSize; |
488 return mAdjustedSize; |
411 } |
489 } |
412 mLastConstraint = constraint; |
490 mLastConstraint = constraint; |
413 |
491 |
414 QSizeF maxSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); |
492 QSizeF maxSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); |
417 } |
495 } |
418 if(constraint.height()>0) { |
496 if(constraint.height()>0) { |
419 maxSize.setHeight(constraint.height()); |
497 maxSize.setHeight(constraint.height()); |
420 } |
498 } |
421 |
499 |
|
500 QString txt(mText); |
|
501 if (constraint.width()>0 && mHasMultiTrans) { |
|
502 // it has to be like that since same aproach is used in rebuildTextLayout |
|
503 // so to be consistent is sizeHInt and what is shown this has to be done |
|
504 txt = metrics.elidedText(mText, Qt::ElideNone, constraint.width()); |
|
505 } |
422 QSizeF size = metrics.boundingRect(QRectF(QPointF(),maxSize), |
506 QSizeF size = metrics.boundingRect(QRectF(QPointF(),maxSize), |
423 textFlagsFromTextOption(), |
507 textFlagsFromTextOption(), |
424 mText).size(); |
508 txt).size(); |
425 |
509 |
426 mAdjustedSize = size; |
510 mAdjustedSize = size; |
427 mDefaultHeight = size.height(); |
511 mDefaultHeight = size.height(); |
428 mMinWidthForAdjust = size.width(); |
512 mMinWidthForAdjust = size.width(); |
429 mMaxWidthForAdjust = maxSize.width(); |
513 mMaxWidthForAdjust = maxSize.width(); |
430 |
514 |
431 #ifdef HB_TEXT_ITEM_LOGS |
515 HB_TEXT_ITEM_PRIV_LOG("returnSize: " << mAdjustedSize |
432 qDebug() << "HbTextItemPrivate::calculatePrefferedSize:" |
|
433 << " text: " << mText.left(KMaxLogedTextLength) |
|
434 << " returnSize: " << mAdjustedSize |
|
435 << " constraint: " << constraint |
516 << " constraint: " << constraint |
436 << " font: " << mTextLayout.font(); |
517 << " font: " << mTextLayout.font()); |
437 #endif |
518 |
438 return size; |
519 return size; |
439 } |
520 } |
440 |
521 |
441 bool HbTextItemPrivate::fadeNeeded(const QRectF& contentRect) const |
522 bool HbTextItemPrivate::fadeNeeded(const QRectF& contentRect) const |
442 { |
523 { |
|
524 QRectF textRect = mBoundingRect.translated(mOffsetPos); |
|
525 textRect.adjust(KFadeTolerance, |
|
526 KFadeTolerance, |
|
527 -KFadeTolerance, |
|
528 -KFadeTolerance); |
443 return (mFadeLengthX!=0 || mFadeLengthY!=0) |
529 return (mFadeLengthX!=0 || mFadeLengthY!=0) |
444 && !contentRect.contains( |
530 && !contentRect.contains(textRect); |
445 layoutBoundingRect().adjusted(KFadeTolerance, |
|
446 KFadeTolerance, |
|
447 -KFadeTolerance, |
|
448 -KFadeTolerance)); |
|
449 } |
531 } |
450 |
532 |
451 void HbTextItemPrivate::setupGradient(QLinearGradient *gradient, QColor color) |
533 void HbTextItemPrivate::setupGradient(QLinearGradient *gradient, QColor color) |
452 { |
534 { |
453 gradient->setColorAt(1.0, color); |
535 gradient->setColorAt(1.0, color); |
511 This work-around is needed since there is a problem with pen transformations |
593 This work-around is needed since there is a problem with pen transformations |
512 in hardware Open VG renderer. This problem occurs only on s60 hardware. |
594 in hardware Open VG renderer. This problem occurs only on s60 hardware. |
513 On platforms: Linux, Windows and S60 emulator there is no such problem. |
595 On platforms: Linux, Windows and S60 emulator there is no such problem. |
514 Below flag detects platform which have this problem to activate work-around. |
596 Below flag detects platform which have this problem to activate work-around. |
515 */ |
597 */ |
516 #if defined(Q_WS_S60) && defined(Q_BIG_ENDIAN) |
598 #if defined(Q_OS_SYMBIAN) && defined(Q_BIG_ENDIAN) |
517 # warning Work-around is active in fade effect of HbTextItem (see comment) |
599 //# warning Work-around is active in fade effect of HbTextItem (see comment) |
518 # define HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
600 # define HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
519 #endif |
601 #endif |
520 inline void HbTextItemPrivate::setPainterPen(QPainter *painter, |
602 inline void HbTextItemPrivate::setPainterPen(QPainter *painter, |
521 const QPen& pen, |
603 const QPen& pen, |
522 const QPointF& lineBegin) |
604 const QPointF& lineBegin) |
832 } |
914 } |
833 } |
915 } |
834 |
916 |
835 QRectF HbTextItemPrivate::layoutBoundingRect () const |
917 QRectF HbTextItemPrivate::layoutBoundingRect () const |
836 { |
918 { |
837 QRectF result; |
919 QRectF result; // (mTextLayout.boundingRect()); |
838 for (int i=0, n=mTextLayout.lineCount(); i<n; ++i) { |
920 for (int i=0, n=mTextLayout.lineCount(); i<n; ++i) { |
839 result = result.unite( |
921 result = result.unite( |
840 mTextLayout.lineAt(i).naturalTextRect()); |
922 mTextLayout.lineAt(i).naturalTextRect()); |
841 } |
923 } |
842 |
924 |
|
925 return result; |
|
926 } |
|
927 |
|
928 QRectF HbTextItemPrivate::boundingRect (const QRectF& contentsRect) const |
|
929 { |
|
930 QRectF result(mBoundingRect); |
843 result.translate(mOffsetPos); |
931 result.translate(mOffsetPos); |
844 |
|
845 return result; |
|
846 } |
|
847 |
|
848 QRectF HbTextItemPrivate::boundingRect (const QRectF& contentsRect) const |
|
849 { |
|
850 QRectF result(layoutBoundingRect()); |
|
851 |
932 |
852 if (mPaintFaded) { |
933 if (mPaintFaded) { |
853 result = result.intersected(mFadeToRect); |
934 result = result.intersected(mFadeToRect); |
854 } |
935 } |
855 |
936 |
982 |
1065 |
983 QString txt( text ); |
1066 QString txt( text ); |
984 |
1067 |
985 #ifdef HB_TEXT_MEASUREMENT_UTILITY |
1068 #ifdef HB_TEXT_MEASUREMENT_UTILITY |
986 |
1069 |
987 if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) { |
1070 if (HbTextMeasurementUtility::instance()->locTestMode()) { |
988 if (text.endsWith(QChar(LOC_TEST_END))) { |
1071 if (text.endsWith(QChar(LOC_TEST_END))) { |
989 int index = text.indexOf(QChar(LOC_TEST_START)); |
1072 int index = text.indexOf(QChar(LOC_TEST_START)); |
990 setProperty( HbTextMeasurementUtilityNameSpace::textIdPropertyName, text.mid(index + 1, text.indexOf(QChar(LOC_TEST_END)) - index - 1) ); |
1073 setProperty( HbTextMeasurementUtilityNameSpace::textIdPropertyName, text.mid(index + 1, text.indexOf(QChar(LOC_TEST_END)) - index - 1) ); |
991 setProperty( HbTextMeasurementUtilityNameSpace::textMaxLines, d->mMaxLines ); |
1074 setProperty( HbTextMeasurementUtilityNameSpace::textMaxLines, d->mMaxLines ); |
992 txt = text.left(index); |
1075 txt = text.left(index); |
999 if (d->mText != txt) { |
1082 if (d->mText != txt) { |
1000 d->scheduleTextBuild(); |
1083 d->scheduleTextBuild(); |
1001 prepareGeometryChange(); |
1084 prepareGeometryChange(); |
1002 d->mText = txt; |
1085 d->mText = txt; |
1003 d->mTextLayout.setCacheEnabled(KLayoutCacheLimit >= d->mText.length()); |
1086 d->mTextLayout.setCacheEnabled(KLayoutCacheLimit >= d->mText.length()); |
|
1087 d->mHasMultiTrans = (txt.indexOf('\x9c')>=0); |
1004 d->clearAdjustedSizeCache(); |
1088 d->clearAdjustedSizeCache(); |
1005 update(); |
1089 update(); |
1006 |
1090 |
1007 // check if call of updateGeometry can be ignored |
1091 // check if call of updateGeometry can be ignored |
1008 // don't call it when minimum and maximum lines are equal (height is fixed) or ... |
1092 // don't call it when minimum and maximum lines are equal (height is fixed) or ... |
1014 |
1098 |
1015 // and when preferred width is ignored |
1099 // and when preferred width is ignored |
1016 if (sizePolicy().horizontalPolicy()&QSizePolicy::IgnoreFlag |
1100 if (sizePolicy().horizontalPolicy()&QSizePolicy::IgnoreFlag |
1017 // or was preferred width set from outside of this class? |
1101 // or was preferred width set from outside of this class? |
1018 || d->mLastConstraint.width()>0) { |
1102 || d->mLastConstraint.width()>0) { |
1019 #ifdef HB_TEXT_ITEM_LOGS |
1103 |
1020 qDebug() << "HbTextItem::setText: skiping updateGeometry for: " |
1104 HB_TEXT_ITEM_LOG("skiping updateGeometry!") |
1021 << objectName() << " text:" << d->mText.left(KMaxLogedTextLength); |
1105 |
1022 #endif |
|
1023 // in those cases skip updateGeometry |
1106 // in those cases skip updateGeometry |
1024 return; |
1107 return; |
1025 } |
1108 } |
1026 } |
1109 } |
1027 updateGeometry(); |
1110 updateGeometry(); |
1065 \sa HbTextItem::alignment() |
1148 \sa HbTextItem::alignment() |
1066 */ |
1149 */ |
1067 void HbTextItem::setAlignment (Qt::Alignment alignment) |
1150 void HbTextItem::setAlignment (Qt::Alignment alignment) |
1068 { |
1151 { |
1069 Q_D(HbTextItem); |
1152 Q_D(HbTextItem); |
1070 d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextAlign, true); |
1153 d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextAlign, true); |
1071 alignment &= Qt::AlignVertical_Mask | Qt::AlignHorizontal_Mask; |
1154 alignment = d->combineAlignment(alignment, d->mAlignment); |
1072 if (d->mAlignment != alignment) { |
1155 if (d->mAlignment != alignment) { |
1073 prepareGeometryChange(); |
1156 prepareGeometryChange(); |
1074 d->mAlignment = alignment; |
1157 d->mAlignment = alignment; |
1075 d->updateTextOption(); |
1158 d->updateTextOption(); |
1076 d->calculateVerticalOffset(); |
1159 d->calculateVerticalOffset(); |
|
1160 d->mBoundingRect = d->layoutBoundingRect(); |
1077 |
1161 |
1078 update(); |
1162 update(); |
1079 } |
1163 } |
1080 } |
1164 } |
1081 |
1165 |
1087 \sa HbTextItem::elideMode() |
1171 \sa HbTextItem::elideMode() |
1088 */ |
1172 */ |
1089 void HbTextItem::setElideMode (Qt::TextElideMode elideMode) |
1173 void HbTextItem::setElideMode (Qt::TextElideMode elideMode) |
1090 { |
1174 { |
1091 Q_D(HbTextItem); |
1175 Q_D(HbTextItem); |
|
1176 d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextElideMode, true); |
1092 if (elideMode != d->mElideMode) { |
1177 if (elideMode != d->mElideMode) { |
1093 d->mElideMode = elideMode; |
1178 d->mElideMode = elideMode; |
1094 d->scheduleTextBuild(); |
1179 d->scheduleTextBuild(); |
1095 prepareGeometryChange(); |
1180 prepareGeometryChange(); |
1096 update(); |
1181 update(); |
1161 if (parentLayoutItem() && parentLayoutItem()->isLayout()) { |
1246 if (parentLayoutItem() && parentLayoutItem()->isLayout()) { |
1162 // rect.size can't be used here since size can be limited inside of |
1247 // rect.size can't be used here since size can be limited inside of |
1163 // called method HbWidgetBase::setGeometry(rect) so size is used which |
1248 // called method HbWidgetBase::setGeometry(rect) so size is used which |
1164 // holds current size |
1249 // holds current size |
1165 Q_D(HbTextItem); |
1250 Q_D(HbTextItem); |
|
1251 if (d->isAdjustWidthNeeded(size().width())) { |
|
1252 updateGeometry(); |
|
1253 HB_TEXT_ITEM_LOG("isAdjustWidthNeeded - updateGeometry was called"); |
|
1254 return; |
|
1255 } |
|
1256 |
1166 if (d->isAdjustHightNeeded(size().width(), |
1257 if (d->isAdjustHightNeeded(size().width(), |
1167 preferredHeight(), |
1258 preferredHeight(), |
1168 minimumHeight(), |
1259 minimumHeight(), |
1169 maximumHeight())) { |
1260 maximumHeight())) { |
1170 updateGeometry(); |
1261 updateGeometry(); |
1171 #ifdef HB_TEXT_ITEM_LOGS |
1262 HB_TEXT_ITEM_LOG("isAdjustHightNeeded - updateGeometry was called"); |
1172 qDebug() << "isAdjustHightNeeded returned true - updateGeometry was called"; |
1263 return; |
1173 #endif // HB_TEXT_ITEM_LOGS |
|
1174 } |
1264 } |
1175 } |
1265 } |
1176 } |
1266 } |
1177 |
1267 |
1178 /*! |
1268 /*! |
1200 QSizeF size(0,0); |
1290 QSizeF size(0,0); |
1201 |
1291 |
1202 // TODO: Temporary work-around - font change event are not always received |
1292 // TODO: Temporary work-around - font change event are not always received |
1203 // so updating font here (this is needed because of sizeHint adjustments). |
1293 // so updating font here (this is needed because of sizeHint adjustments). |
1204 if (d->mTextLayout.font()!=font()) { |
1294 if (d->mTextLayout.font()!=font()) { |
1205 #ifdef HB_TEXT_ITEM_LOGS |
1295 HB_TEXT_ITEM_LOG("Font change was not recieved on time: work-around is active" |
1206 qWarning() << "Font change was not recieved on time: work-around is active" |
|
1207 << objectName() |
|
1208 << " test: " << d->mText.left(KMaxLogedTextLength) |
|
1209 << " oldFont:" << d->mTextLayout.font() |
1296 << " oldFont:" << d->mTextLayout.font() |
1210 << " newFont:" << font(); |
1297 << " newFont:" << font()) |
1211 #endif // HB_TEXT_ITEM_LOGS |
|
1212 |
1298 |
1213 const_cast<HbTextItemPrivate *>(d)->mTextLayout.setFont(font()); |
1299 const_cast<HbTextItemPrivate *>(d)->mTextLayout.setFont(font()); |
1214 const_cast<HbTextItemPrivate *>(d)->clearAdjustedSizeCache(); |
1300 const_cast<HbTextItemPrivate *>(d)->clearAdjustedSizeCache(); |
1215 } |
1301 } |
1216 |
1302 |
1264 |
1350 |
1265 Detects: font changes, layout direction changes and theme changes. |
1351 Detects: font changes, layout direction changes and theme changes. |
1266 */ |
1352 */ |
1267 void HbTextItem::changeEvent(QEvent *event) |
1353 void HbTextItem::changeEvent(QEvent *event) |
1268 { |
1354 { |
1269 // Listens theme changed event so that item size hint is |
|
1270 |
|
1271 switch(event->type()) { |
1355 switch(event->type()) { |
1272 case QEvent::LayoutDirectionChange: { |
1356 case QEvent::LayoutDirectionChange: { |
1273 Q_D(HbTextItem); |
1357 Q_D(HbTextItem); |
1274 d->scheduleTextBuild(); |
1358 d->scheduleTextBuild(); |
|
1359 prepareGeometryChange(); |
1275 } |
1360 } |
1276 break; |
1361 break; |
1277 |
1362 |
1278 case QEvent::FontChange: { |
1363 case QEvent::FontChange: { |
1279 Q_D(HbTextItem); |
1364 Q_D(HbTextItem); |
1280 |
1365 |
1281 if (!d->mTextLayout.font().isCopyOf(font())) { |
1366 if (!d->mTextLayout.font().isCopyOf(font())) { |
1282 |
1367 HB_TEXT_ITEM_LOG(" font: " << font()); |
1283 #ifdef HB_TEXT_ITEM_LOGS |
|
1284 qDebug() << "fontChangeEvent: " << objectName() |
|
1285 << " text: " << text().left(KMaxLogedTextLength) |
|
1286 << " font: " << font(); |
|
1287 #endif // HB_TEXT_ITEM_LOGS |
|
1288 |
1368 |
1289 d->mTextLayout.setFont(font()); |
1369 d->mTextLayout.setFont(font()); |
1290 d->clearAdjustedSizeCache(); |
1370 d->clearAdjustedSizeCache(); |
1291 d->scheduleTextBuild(); |
1371 d->scheduleTextBuild(); |
1292 prepareGeometryChange(); |
1372 prepareGeometryChange(); |
1333 \sa QTextOption::setWrapMode |
1413 \sa QTextOption::setWrapMode |
1334 */ |
1414 */ |
1335 void HbTextItem::setTextWrapping(Hb::TextWrapping mode) |
1415 void HbTextItem::setTextWrapping(Hb::TextWrapping mode) |
1336 { |
1416 { |
1337 Q_D(HbTextItem); |
1417 Q_D(HbTextItem); |
1338 d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextWrapMode, true); |
1418 d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextWrapMode, true); |
1339 QTextOption::WrapMode textWrapMode = static_cast<QTextOption::WrapMode>(mode); |
1419 QTextOption::WrapMode textWrapMode = static_cast<QTextOption::WrapMode>(mode); |
1340 |
1420 |
1341 QTextOption textOption = d->mTextLayout.textOption(); |
1421 QTextOption textOption = d->mTextLayout.textOption(); |
1342 if(textOption.wrapMode()!=textWrapMode) { |
1422 if(textOption.wrapMode()!=textWrapMode) { |
1343 textOption.setWrapMode(textWrapMode); |
1423 textOption.setWrapMode(textWrapMode); |
1440 void HbTextItem::setMinimumLines( int minLines ) |
1520 void HbTextItem::setMinimumLines( int minLines ) |
1441 { |
1521 { |
1442 Q_D( HbTextItem ); |
1522 Q_D( HbTextItem ); |
1443 minLines = qMax(minLines, 1); // zero or nagative values are meanless and are restoring 1 |
1523 minLines = qMax(minLines, 1); // zero or nagative values are meanless and are restoring 1 |
1444 |
1524 |
1445 d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMin, true); |
1525 d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMin, true); |
1446 |
1526 |
1447 if( minLines != d->mMinLines ) { |
1527 if( minLines != d->mMinLines ) { |
1448 if( ( d->mMaxLines > 0 ) && ( minLines > d->mMaxLines ) ) { |
1528 if( ( d->mMaxLines > 0 ) && ( minLines > d->mMaxLines ) ) { |
1449 d->mMaxLines = minLines; |
1529 d->mMaxLines = minLines; |
1450 } |
1530 } |
1469 \sa HbTextItem::minimumLines() |
1549 \sa HbTextItem::minimumLines() |
1470 */ |
1550 */ |
1471 void HbTextItem::setMaximumLines( int maxLines ) |
1551 void HbTextItem::setMaximumLines( int maxLines ) |
1472 { |
1552 { |
1473 Q_D( HbTextItem ); |
1553 Q_D( HbTextItem ); |
1474 d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMax, true); |
1554 d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMax, true); |
1475 |
1555 |
1476 maxLines = qMax(maxLines, 0); |
1556 maxLines = qMax(maxLines, 0); |
1477 |
1557 |
1478 if( maxLines != d->mMaxLines ) { |
1558 if( maxLines != d->mMaxLines ) { |
1479 if ((maxLines > 0) && (maxLines < d->mMinLines)){ |
1559 if ((maxLines > 0) && (maxLines < d->mMinLines)){ |