diff -r 7516d6d86cf5 -r ed14f46c0e55 src/hbcore/primitives/hbtextitem.cpp --- a/src/hbcore/primitives/hbtextitem.cpp Mon Oct 04 17:49:30 2010 +0300 +++ b/src/hbcore/primitives/hbtextitem.cpp Mon Oct 18 18:23:13 2010 +0300 @@ -37,17 +37,30 @@ #include #ifdef HB_TEXT_MEASUREMENT_UTILITY -#include "hbtextmeasurementutility_p.h" -#include "hbfeaturemanager_r.h" +#include "hbtextmeasurementutility_r.h" +#include "hbtextmeasurementutility_r_p.h" #endif -// #define HB_TEXT_ITEM_LOGS #define EPSILON 0.01 -#ifdef HB_TEXT_ITEM_LOGS -# include -const int KMaxLogedTextLength = 30; -#endif // HB_TEXT_ITEM_LOGS +// #define HB_DEBUG_TEXT_ITEM_LOGS +#ifdef HB_DEBUG_TEXT_ITEM_LOGS + #include + + #define HB_TEXT_ITEM_LOG(args) qDebug() << "HbTextItem::" << __FUNCTION__ \ + << "(" << __LINE__ << ")"\ + << ", objectName:" << this->objectName() \ + << ", text: " << this->text().left(30) \ + << " " << args; + #define HB_TEXT_ITEM_PRIV_LOG(args) qDebug() << "HbTextItemPrivate::" << __FUNCTION__ \ + << "(" << __LINE__ << ")"\ + << ", objectName:" << q_ptr->objectName() \ + << ", text: " << this->mText.left(30) \ + << " " << args; +#else + #define HB_TEXT_ITEM_LOG(args) + #define HB_TEXT_ITEM_PRIV_LOG(args) +#endif // HB_DEBUG_TEXT_ITEM_LOGS bool HbTextItemPrivate::outlinesEnabled = false; @@ -69,15 +82,17 @@ mMinWidthForAdjust(-1), mMaxWidthForAdjust(-1), mDefaultHeight(-1), + mHasMultiTrans(false), mUpdateColor(true), - mEventPosted(false) + mEventPosted(false), + inConstructor(1) { } void HbTextItemPrivate::init(QGraphicsItem *) { Q_Q(HbTextItem); - + inConstructor = 1; q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); q->setFlag(QGraphicsItem::ItemClipsToShape, false); q->setFlag(QGraphicsItem::ItemIsSelectable, false); @@ -88,6 +103,7 @@ mTextLayout.setTextOption(textOption); mTextLayout.setCacheEnabled(true); mTextLayout.setFont(q->font()); + inConstructor = 0; } void HbTextItemPrivate::clear() @@ -136,7 +152,7 @@ tempText.replace('\n', QChar::LineSeparator); } - // Need to call elidedText explicitly to enable multiple length translations. + // Need to call elidedText explicitly to enable multiple length translations. tempText = fontMetrics.elidedText(tempText, Qt::ElideNone, lineWidth); bool textTruncated = doLayout(tempText, lineWidth, fontMetrics.lineSpacing()); @@ -152,6 +168,7 @@ } calculateVerticalOffset(); + mBoundingRect = layoutBoundingRect(); calculateFadeRects(); // build of text layout is completed @@ -217,8 +234,8 @@ elidedText.append(QChar::LineSeparator); } - int n = lastLine.textLength(); - if(textToElide.at(lastLine.textStart()+n-1)!=QChar::LineSeparator) { + int n = lastLine.textLength()-1; + if(textToElide.at(lastLine.textStart()+n)!=QChar::LineSeparator) { n = -1; } elidedText.append(metrics.elidedText(textToElide.mid(lastLine.textStart(), n), @@ -303,16 +320,6 @@ qreal minHeight, qreal maxHeight) { -#ifdef HB_TEXT_ITEM_LOGS - qDebug() << "isAdjustHightNeeded for: " << q_ptr->objectName() - << " text=" << mText.left(KMaxLogedTextLength) - << " adjusted=" << mAdjustedSize - << " prefHeight=" << prefHeight - << " minHeight=" << minHeight - << " lastConstraint=" << mLastConstraint - << " " << mTextLayout.font(); -#endif // HB_TEXT_ITEM_LOGS - // first check if wrapping of text is not active QTextOption::WrapMode wrapMode = mTextLayout.textOption().wrapMode(); if (wrapMode==QTextOption::NoWrap @@ -330,6 +337,12 @@ return false; } + HB_TEXT_ITEM_PRIV_LOG("adjusted=" << mAdjustedSize + << " prefHeight=" << prefHeight + << " minHeight=" << minHeight + << " lastConstraint=" << mLastConstraint + << " " << mTextLayout.font()) + // check if adjusted size has been already calculated // new width is bigger then last estimated range of same height if ((mMaxWidthForAdjust>=newWidth @@ -347,10 +360,16 @@ // if preconditions are met test if current hight is enough const QFontMetricsF metrics(mTextLayout.font()); + QString txt(mText); + if (mHasMultiTrans) { + // it has to be like that since same aproach is used in rebuildTextLayout + // so to be consistent is sizeHInt and what is shown this has to be done + txt = metrics.elidedText(mText, Qt::ElideNone, newWidth); + } // heavy calculation: check if text fits in current size and cache result QSizeF newAdjust = metrics.boundingRect(QRectF(0, 0, newWidth, QWIDGETSIZE_MAX), textFlagsFromTextOption(), - mText).size(); + txt).size(); if (qFuzzyCompare(newAdjust.height(), mAdjustedSize.height())) { // height is same as last time update range of same height @@ -385,6 +404,67 @@ return true; } +bool HbTextItemPrivate::isAdjustWidthNeeded(qreal newWidth) +{ + if (!mHasMultiTrans) { + return false; + } + + if (mLastConstraint.width()>0) { + return false; + } // check if adjusted size has been already calculated + // new width is bigger then last estimated range of same height + + if (!mAdjustedSize.isValid()) { + // this means that preferred size is set outside of class by setPreferredSize + // so sizeHint(Qt::Preferredsize) was not called and size adjustment is useless + return false; + } + + HB_TEXT_ITEM_PRIV_LOG("oldadjusted=" << mAdjustedSize + << " newWidth=" << newWidth + << " lastConstraint=" << mLastConstraint) + + if ((mMaxWidthForAdjust>=newWidth + // new width is smaller then last estimated range of same height + && newWidth>=mMinWidthForAdjust)) { + return false; + } + + QFontMetricsF metrics(q_ptr->font()); + + // heavy calculation: check if text fits in current size and cache result + // note that no wrapping is used here since full width of text is needed to return + // proper preferred sizeHint + QSizeF newAdjust = metrics.boundingRect(QRectF(0, 0, newWidth, QWIDGETSIZE_MAX), + 0, + mText).size(); + + if (qFuzzyCompare(newAdjust.width(), mAdjustedSize.width())) { + return false; + } + + if (mAdjustedSize.width()newWidth) { + qWarning("Provided multiple translation: \"%s\", " + "has wrong order of possible translations. " + "This could lead to infinitive loop of LayoutRequest events.", + mText.toLatin1().data()); + + return false; + } + mAdjustedSize = newAdjust; + + mMaxWidthForAdjust = mMinWidthForAdjust = newAdjust.width(); + // it must be like this since it is unknown if there will be next resize or not + // size hint width is changed so change of width can occur and wrapping can be active + + HB_TEXT_ITEM_PRIV_LOG("newAdjusted=" << mAdjustedSize + << " newWidth=" << newWidth) + + return true; +} + void HbTextItemPrivate::clearAdjustedSizeCache() { // clear cache of size @@ -402,11 +482,9 @@ // - HbTextItemPrivate::isAdjustHightNeeded // - HbTextItem::resizeEvent -#ifdef HB_TEXT_ITEM_LOGS - qDebug() << "HbTextItemPrivate::calculatePrefferedSize: returning cached value: " << mAdjustedSize - << " font:" << mTextLayout.font() - << " text:" << mText.left(KMaxLogedTextLength); -#endif + HB_TEXT_ITEM_PRIV_LOG("mAdjustedSize: " << mAdjustedSize + << " font:" << mTextLayout.font()) + return mAdjustedSize; } mLastConstraint = constraint; @@ -419,33 +497,37 @@ maxSize.setHeight(constraint.height()); } + QString txt(mText); + if (constraint.width()>0 && mHasMultiTrans) { + // it has to be like that since same aproach is used in rebuildTextLayout + // so to be consistent is sizeHInt and what is shown this has to be done + txt = metrics.elidedText(mText, Qt::ElideNone, constraint.width()); + } QSizeF size = metrics.boundingRect(QRectF(QPointF(),maxSize), textFlagsFromTextOption(), - mText).size(); + txt).size(); mAdjustedSize = size; mDefaultHeight = size.height(); mMinWidthForAdjust = size.width(); mMaxWidthForAdjust = maxSize.width(); -#ifdef HB_TEXT_ITEM_LOGS - qDebug() << "HbTextItemPrivate::calculatePrefferedSize:" - << " text: " << mText.left(KMaxLogedTextLength) - << " returnSize: " << mAdjustedSize + HB_TEXT_ITEM_PRIV_LOG("returnSize: " << mAdjustedSize << " constraint: " << constraint - << " font: " << mTextLayout.font(); -#endif + << " font: " << mTextLayout.font()); + return size; } bool HbTextItemPrivate::fadeNeeded(const QRectF& contentRect) const { + QRectF textRect = mBoundingRect.translated(mOffsetPos); + textRect.adjust(KFadeTolerance, + KFadeTolerance, + -KFadeTolerance, + -KFadeTolerance); return (mFadeLengthX!=0 || mFadeLengthY!=0) - && !contentRect.contains( - layoutBoundingRect().adjusted(KFadeTolerance, - KFadeTolerance, - -KFadeTolerance, - -KFadeTolerance)); + && !contentRect.contains(textRect); } void HbTextItemPrivate::setupGradient(QLinearGradient *gradient, QColor color) @@ -513,8 +595,8 @@ On platforms: Linux, Windows and S60 emulator there is no such problem. Below flag detects platform which have this problem to activate work-around. */ -#if defined(Q_WS_S60) && defined(Q_BIG_ENDIAN) -# warning Work-around is active in fade effect of HbTextItem (see comment) +#if defined(Q_OS_SYMBIAN) && defined(Q_BIG_ENDIAN) +//# warning Work-around is active in fade effect of HbTextItem (see comment) # define HB_FADE_EFFECT_WORKAROUND_ON_PHONE #endif inline void HbTextItemPrivate::setPainterPen(QPainter *painter, @@ -834,20 +916,19 @@ QRectF HbTextItemPrivate::layoutBoundingRect () const { - QRectF result; + QRectF result; // (mTextLayout.boundingRect()); for (int i=0, n=mTextLayout.lineCount(); iinit(parent); + d->inConstructor = 1; setText(text); + d->inConstructor = 0; } /* @@ -984,7 +1067,7 @@ #ifdef HB_TEXT_MEASUREMENT_UTILITY - if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) { + if (HbTextMeasurementUtility::instance()->locTestMode()) { if (text.endsWith(QChar(LOC_TEST_END))) { int index = text.indexOf(QChar(LOC_TEST_START)); setProperty( HbTextMeasurementUtilityNameSpace::textIdPropertyName, text.mid(index + 1, text.indexOf(QChar(LOC_TEST_END)) - index - 1) ); @@ -1001,6 +1084,7 @@ prepareGeometryChange(); d->mText = txt; d->mTextLayout.setCacheEnabled(KLayoutCacheLimit >= d->mText.length()); + d->mHasMultiTrans = (txt.indexOf('\x9c')>=0); d->clearAdjustedSizeCache(); update(); @@ -1016,10 +1100,9 @@ if (sizePolicy().horizontalPolicy()&QSizePolicy::IgnoreFlag // or was preferred width set from outside of this class? || d->mLastConstraint.width()>0) { -#ifdef HB_TEXT_ITEM_LOGS - qDebug() << "HbTextItem::setText: skiping updateGeometry for: " - << objectName() << " text:" << d->mText.left(KMaxLogedTextLength); -#endif + + HB_TEXT_ITEM_LOG("skiping updateGeometry!") + // in those cases skip updateGeometry return; } @@ -1067,13 +1150,14 @@ void HbTextItem::setAlignment (Qt::Alignment alignment) { Q_D(HbTextItem); - d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextAlign, true); - alignment &= Qt::AlignVertical_Mask | Qt::AlignHorizontal_Mask; + d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextAlign, true); + alignment = d->combineAlignment(alignment, d->mAlignment); if (d->mAlignment != alignment) { prepareGeometryChange(); d->mAlignment = alignment; d->updateTextOption(); d->calculateVerticalOffset(); + d->mBoundingRect = d->layoutBoundingRect(); update(); } @@ -1089,6 +1173,7 @@ void HbTextItem::setElideMode (Qt::TextElideMode elideMode) { Q_D(HbTextItem); + d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextElideMode, true); if (elideMode != d->mElideMode) { d->mElideMode = elideMode; d->scheduleTextBuild(); @@ -1163,14 +1248,19 @@ // called method HbWidgetBase::setGeometry(rect) so size is used which // holds current size Q_D(HbTextItem); + if (d->isAdjustWidthNeeded(size().width())) { + updateGeometry(); + HB_TEXT_ITEM_LOG("isAdjustWidthNeeded - updateGeometry was called"); + return; + } + if (d->isAdjustHightNeeded(size().width(), preferredHeight(), minimumHeight(), maximumHeight())) { - updateGeometry(); -#ifdef HB_TEXT_ITEM_LOGS - qDebug() << "isAdjustHightNeeded returned true - updateGeometry was called"; -#endif // HB_TEXT_ITEM_LOGS + updateGeometry(); + HB_TEXT_ITEM_LOG("isAdjustHightNeeded - updateGeometry was called"); + return; } } } @@ -1202,13 +1292,9 @@ // TODO: Temporary work-around - font change event are not always received // so updating font here (this is needed because of sizeHint adjustments). if (d->mTextLayout.font()!=font()) { -#ifdef HB_TEXT_ITEM_LOGS - qWarning() << "Font change was not recieved on time: work-around is active" - << objectName() - << " test: " << d->mText.left(KMaxLogedTextLength) + HB_TEXT_ITEM_LOG("Font change was not recieved on time: work-around is active" << " oldFont:" << d->mTextLayout.font() - << " newFont:" << font(); -#endif // HB_TEXT_ITEM_LOGS + << " newFont:" << font()) const_cast(d)->mTextLayout.setFont(font()); const_cast(d)->clearAdjustedSizeCache(); @@ -1266,12 +1352,11 @@ */ void HbTextItem::changeEvent(QEvent *event) { - // Listens theme changed event so that item size hint is - switch(event->type()) { case QEvent::LayoutDirectionChange: { Q_D(HbTextItem); d->scheduleTextBuild(); + prepareGeometryChange(); } break; @@ -1279,12 +1364,7 @@ Q_D(HbTextItem); if (!d->mTextLayout.font().isCopyOf(font())) { - -#ifdef HB_TEXT_ITEM_LOGS - qDebug() << "fontChangeEvent: " << objectName() - << " text: " << text().left(KMaxLogedTextLength) - << " font: " << font(); -#endif // HB_TEXT_ITEM_LOGS + HB_TEXT_ITEM_LOG(" font: " << font()); d->mTextLayout.setFont(font()); d->clearAdjustedSizeCache(); @@ -1335,7 +1415,7 @@ void HbTextItem::setTextWrapping(Hb::TextWrapping mode) { Q_D(HbTextItem); - d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextWrapMode, true); + d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextWrapMode, true); QTextOption::WrapMode textWrapMode = static_cast(mode); QTextOption textOption = d->mTextLayout.textOption(); @@ -1442,7 +1522,7 @@ Q_D( HbTextItem ); minLines = qMax(minLines, 1); // zero or nagative values are meanless and are restoring 1 - d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMin, true); + d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMin, true); if( minLines != d->mMinLines ) { if( ( d->mMaxLines > 0 ) && ( minLines > d->mMaxLines ) ) { @@ -1471,7 +1551,7 @@ void HbTextItem::setMaximumLines( int maxLines ) { Q_D( HbTextItem ); - d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMax, true); + d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMax, true); maxLines = qMax(maxLines, 0); @@ -1487,7 +1567,7 @@ updateGeometry(); #ifdef HB_TEXT_MEASUREMENT_UTILITY - if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) { + if (HbTextMeasurementUtility::instance()->locTestMode()) { setProperty( HbTextMeasurementUtilityNameSpace::textMaxLines, d->mMaxLines ); } #endif @@ -1584,4 +1664,16 @@ d->setFadeLengths(lengths.x(), lengths.y()); } +/*! + \reimp + */ +void HbTextItem::updateGeometry() +{ + Q_D( HbTextItem ); + if (d->inConstructor) { + return; + } + HbWidgetBase::updateGeometry(); +} + // end of file