src/hbcore/primitives/hbtextitem.cpp
changeset 6 c3690ec91ef8
parent 3 11d3954df52a
child 7 923ff622b8b9
--- a/src/hbcore/primitives/hbtextitem.cpp	Fri Jun 11 13:58:22 2010 +0300
+++ b/src/hbcore/primitives/hbtextitem.cpp	Wed Jun 23 18:33:25 2010 +0300
@@ -38,15 +38,20 @@
 
 #ifdef HB_TEXT_MEASUREMENT_UTILITY
 #include "hbtextmeasurementutility_p.h"
-#include "hbfeaturemanager_p.h"
+#include "hbfeaturemanager_r.h"
 #endif
 
+// #define HB_TEXT_ITEM_LOGS
 #define EPSILON 0.01
 
+#ifdef HB_TEXT_ITEM_LOGS
+#   include <QDebug>
+#endif // HB_TEXT_ITEM_LOGS
+
 bool HbTextItemPrivate::outlinesEnabled = false;
 
 static const QString KDefaultColorThemeName = "qtc_view_normal";
-const int MinimumWidth = 5; // minimum width if there is some text.
+const qreal MinimumWidth = 5.0; // minimum width if there is some text.
 const int KLayoutCacheLimit = 64;
 const qreal KFadeTolerance = 1.0;
 
@@ -58,11 +63,13 @@
     mPaintFaded(false),
     mFadeLengthX(30),
     mFadeLengthY(15),
-    mPrefHeight(0),
-    mMinLines(0),
+    mMinLines(1),
     mMaxLines(0),
-    mNeedToAdjustSizeHint(false),
-    mUpdateColor(true)
+    mMinWidthForAdjust(-1),
+    mMaxWidthForAdjust(-1),
+    mDefaultHeight(-1),
+    mUpdateColor(true),
+    mEventPosted(false)
 {
 }
 
@@ -79,6 +86,7 @@
     textOption.setWrapMode(QTextOption::WordWrap);
     mTextLayout.setTextOption(textOption);
     mTextLayout.setCacheEnabled(true);
+    mTextLayout.setFont(q->font());
 }
 
 void HbTextItemPrivate::clear()
@@ -86,57 +94,36 @@
     // no implementation needed
 }
 
-bool HbTextItemPrivate::doLayout(const QString& text, const qreal lineWidth, qreal leading)
+bool HbTextItemPrivate::doLayout(const QString& text, const qreal lineWidth, qreal lineSpacing)
 {
     bool textTruncated = false;
-    mInvalidateShownText = false;
 
     mTextLayout.setText(text);
-    mTextLayout.setFont( q_func()->font() );
 
-    qreal height = 0;
+    qreal yLinePos = 0;
     mTextLayout.beginLayout();
     while (1) {
         QTextLine line = mTextLayout.createLine();
         if (!line.isValid())
             break;
-        if( ( mMaxLines > 0 ) && ( mTextLayout.lineCount() > mMaxLines ) ) {
-            textTruncated = true;
+
+        line.setLineWidth(lineWidth);
+        line.setPosition(QPointF(0, yLinePos));
+
+        if( ( mMaxLines > 0 ) && ( mTextLayout.lineCount() >= mMaxLines ) ) {
+            textTruncated = (line.textStart()+line.textLength() < text.length());
             break;
         }
-
-        line.setLineWidth(lineWidth);
-        height += leading;
-        line.setPosition(QPointF(0, height));
-        height += line.height();
+        yLinePos += lineSpacing;
     }
     mTextLayout.endLayout();
 
-    if( textTruncated ) {
-        mTextLayout.setText(text);
-        mTextLayout.setFont( q_func()->font() );
-
-        qreal height = 0;
-        mTextLayout.beginLayout();
-        while ( mTextLayout.lineCount() < mMaxLines ) {
-            QTextLine line = mTextLayout.createLine();
-            line.setLineWidth(lineWidth);
-            height += leading;
-            line.setPosition(QPointF(0, height));
-            height += line.height();
-        }
-        mTextLayout.endLayout();
-    }
-
     return textTruncated;
 }
 
-void HbTextItemPrivate::setSize(const QSizeF &newSize)
+void HbTextItemPrivate::rebuildTextLayout(const QSizeF &newSize)
 {
-    Q_Q(HbTextItem);
-
-    QFont usedFont = q->font();
-    QFontMetricsF fontMetrics(usedFont);
+    QFontMetricsF fontMetrics(mTextLayout.font());
 
     const qreal lineWidth = qRound( newSize.width() + 0.5 ); // round up to integer
 
@@ -148,11 +135,10 @@
         tempText.replace('\n', QChar::LineSeparator);
     }
 
-    // function does the layout only when needed
-    mTextLayout.setFont(usedFont);
 	// Need to call elidedText explicitly to enable multiple length translations.
     tempText = fontMetrics.elidedText(tempText, Qt::ElideNone, lineWidth);
-    bool textTruncated = doLayout(tempText, lineWidth, fontMetrics.leading());
+    bool textTruncated = doLayout(tempText, lineWidth, fontMetrics.lineSpacing());
+
     if(mElideMode!=Qt::ElideNone && !tempText.isEmpty()) {
         if( ( mTextLayout.boundingRect().height() - newSize.height() > EPSILON ) ||
             ( mTextLayout.boundingRect().width() - lineWidth > EPSILON ) ||
@@ -160,12 +146,15 @@
             // TODO: Multiple length translations with multiline text
             doLayout(elideLayoutedText(newSize, fontMetrics),
                      lineWidth,
-                     fontMetrics.leading());
+                     fontMetrics.lineSpacing());
         }
     }
+
     calculateVerticalOffset();
     calculateFadeRects();
-    q->update();
+
+    // build of text layout is completed
+    mInvalidateShownText = false;
 }
 
 /*
@@ -194,6 +183,25 @@
     return i;
 }
 
+QSizeF HbTextItemPrivate::respectSizeLimits(QSizeF size) const
+{
+    QFontMetricsF metrics(mTextLayout.font());
+
+    Q_ASSERT(mMinLines>0);
+    qreal minHeight = metrics.lineSpacing()*mMinLines - metrics.leading();
+    if (size.height()<minHeight) {
+        size.setHeight(minHeight);
+    }
+
+    if (mMaxLines>0) {
+        qreal maxHeight = metrics.lineSpacing()*mMaxLines - metrics.leading();
+        if (size.height()>maxHeight) {
+            size.setHeight(maxHeight);
+        }
+    }
+    return size;
+}
+
 QString HbTextItemPrivate::elideLayoutedText(const QSizeF& size, const QFontMetricsF& metrics) const
 {
     int lastVisibleLine =findIndexOfLastLineBeforeY(size.height());
@@ -280,38 +288,134 @@
     return flags;
 }
 
-bool HbTextItemPrivate::adjustSizeHint()
-{
-    Q_Q( HbTextItem );
+/*!
+    This method check spetial case of calculating sizeHint.
+    By default prefferedSize returns size of text which has lots of free space.
+    But there can be situaltion that text has less avaible free width ther requred.
+    In such cases prefered hight of HbTextItem should be recaculated because wrapping
+    of the line may requre more space in vertical direction.
 
-    mNeedToAdjustSizeHint = false;
-
-    if ( !(q->sizePolicy().verticalPolicy()&QSizePolicy::IgnoreFlag) ) {
-        // only calculated if the vertical sizeHint is taken into account
-
-        const QFontMetricsF metrics(q->font());
+    In such case bigger hight should be cached for sizeHint calculations.
+ */
+bool HbTextItemPrivate::isAdjustHightNeeded(const QSizeF& newSize,
+                                            const QSizeF& prefSize)
+{
+#ifdef HB_TEXT_ITEM_LOGS
+    qDebug() << "isAdjustHightNeeded for: " << q_ptr->objectName()
+            << " text=" << mText.left(20)
+            << " adjusted=" << mAdjustedSize
+            << " pref=" << prefSize
+            << mTextLayout.font();
+#endif // HB_TEXT_ITEM_LOGS
 
-        if ( mMinLines > 0 && (mMinLines == mMaxLines) ) {
-            // if the number of lines if fixed: optimize
-            const qreal newPrefHeight = ( metrics.height() + metrics.leading() ) * mMinLines - metrics.leading();
-            if( qAbs( mPrefHeight - newPrefHeight ) > EPSILON ) {
-                mPrefHeight = newPrefHeight;
-                return true;
-            }
-            return false;
-        }
+    // first check if wrapping of text is not active
+    QTextOption::WrapMode wrapMode = mTextLayout.textOption().wrapMode();
+    if (wrapMode==QTextOption::NoWrap
+        || wrapMode==QTextOption::ManualWrap) {
+        return false;
+    }
+
+    // check if line count is fixed
+    if (mMaxLines == mMinLines) {
+        return false;
+    }
 
-        QSizeF currSize = q->size();
-        // do the heavy calculation
-        QRectF desiredRect = metrics.boundingRect( QRectF( 0, 0 , currSize.width(), QWIDGETSIZE_MAX ), textFlagsFromTextOption(), mText );
+    // check if preffered height is defined by user
+    //    so check if preff height is same as value returned by sizeHint
+    if (!qFuzzyCompare(prefSize.height(), mAdjustedSize.height())) {
+        return false;
+    }
 
-        if( qAbs( desiredRect.height() - mPrefHeight ) > EPSILON ) {
-            mPrefHeight = desiredRect.height();
-            return true;
-        }
+    // check if adjusted size has been already calculated
+    // new width is bigger then last estimated range of same height
+    if ((mMaxWidthForAdjust>=newSize.width()
+        // new width is smaller then last estimated range of same height
+        && newSize.width()>=mMinWidthForAdjust)) {
+        return false;
+    }
+
+    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;
     }
 
-    return false;
+    // if preconditions are met test if current hight is enough
+    const QFontMetricsF metrics(mTextLayout.font());
+
+    // heavy calculation: check if text fits in current size and cache result
+    QSizeF newAdjust = metrics.boundingRect(QRectF(0, 0, newSize.width(), QWIDGETSIZE_MAX),
+                                       textFlagsFromTextOption(),
+                                       mText).size();
+
+    if (qFuzzyCompare(newAdjust.height(), mAdjustedSize.height())) {
+        // height is same as last time update range of same height
+        mMaxWidthForAdjust = qMax(mMaxWidthForAdjust, newSize.width());
+        mMinWidthForAdjust = qMin(mMinWidthForAdjust, newSize.width());
+
+        // and don't update geometry
+        return false;
+    }
+
+    // new height was calculated create new range for which
+    // current mAdjustedSize.height is valid
+    mMaxWidthForAdjust = newSize.width();
+    mMinWidthForAdjust = newAdjust.width();
+
+    // store new hieght use don't change width
+    mAdjustedSize.setHeight(newAdjust.height());
+    Q_ASSERT_X(mAdjustedSize.width()>=newAdjust.width(),
+               "HbTextItemPrivate::isAdjustHightNeeded",
+               QString("Fail for string: \"%1\"").arg(mText).toAscii().data());
+
+    if (respectSizeLimits(mAdjustedSize)==prefSize) {
+        // updateGeometry has no effect
+        return false;
+    }
+
+    // all conditions for calling updateGeometry are meet
+    return true;
+}
+
+void HbTextItemPrivate::clearAdjustedSizeCache()
+{
+    // clear cache of size
+    mMinWidthForAdjust = -1;
+    mMaxWidthForAdjust = -1;
+    mAdjustedSize.setHeight(-1);
+}
+
+QSizeF HbTextItemPrivate::calculatePrefferedSize(const QSizeF& constraint) const
+{
+    const QFontMetricsF metrics(mTextLayout.font());
+
+    if (mAdjustedSize.isValid() &&
+        (constraint.height()<0 || qFuzzyCompare(constraint.height(), mAdjustedSize.height())) &&
+        (constraint.width()<0  || qFuzzyCompare(constraint.width(), mAdjustedSize.width()))) {
+        // return cached value, see more in:
+        //      - HbTextItemPrivate::isAdjustHightNeeded
+        //      - HbTextItem::resizeEvent
+        return mAdjustedSize;
+    }
+
+    QSizeF maxSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+    if(constraint.width()>0) {
+        maxSize.setWidth(constraint.width());
+    }
+    if(constraint.height()>0) {
+        maxSize.setHeight(constraint.height());
+    }
+
+    QSizeF size = metrics.boundingRect(QRectF(QPointF(),maxSize),
+                                       textFlagsFromTextOption(),
+                                       mText).size();
+
+    mAdjustedSize = size;
+    mDefaultHeight = size.height();
+    mMinWidthForAdjust = size.width();
+    mMaxWidthForAdjust = QWIDGETSIZE_MAX;
+
+    return size;
 }
 
 bool HbTextItemPrivate::fadeNeeded(const QRectF& contentRect) const
@@ -532,7 +636,6 @@
 
 // #define SEE_FADE_RECTANGLES
 #ifdef SEE_FADE_RECTANGLES
-    painter->setClipRect(mFadeToRect);
     painter->setBrush(QBrush(QColor(215, 0, 0, 30)));
     painter->drawRect(mFadeToRect);
     painter->setBrush(QBrush(QColor(0, 0, 200, 30)));
@@ -743,6 +846,11 @@
     return result;
 }
 
+void HbTextItemPrivate::scheduleTextBuild()
+{
+    mInvalidateShownText = true;
+}
+
 /*!
     @alpha
     @hbcore
@@ -757,7 +865,6 @@
 /*!
     Constructor for the class with no content.
  */
-
 HbTextItem::HbTextItem (QGraphicsItem *parent) :
     HbWidgetBase(*new HbTextItemPrivate, parent)
 {
@@ -872,21 +979,30 @@
 #endif //HB_TEXT_MEASUREMENT_UTILITY
 
     if (d->mText != txt) {
-        d->mInvalidateShownText = true;
+        d->scheduleTextBuild();
         prepareGeometryChange();
         d->mText = txt;
         d->mTextLayout.setCacheEnabled(KLayoutCacheLimit >= d->mText.length());
-        bool onlyHorizontalSizeHintChanged = false;
-        if ( d->mMinLines > 0 && (d->mMinLines == d->mMaxLines) ) {
-            onlyHorizontalSizeHintChanged = true;
+        d->clearAdjustedSizeCache();
+        update();
+
+        // check if call of updateGeometry can be ignored
+        // don't call it when minimum and maximum lines are equal (height is fixed) or ...
+        if ((d->mMinLines == d->mMaxLines)
+            // or when preferred height is ignored
+            || (sizePolicy().verticalPolicy()&QSizePolicy::IgnoreFlag)) {
+
+            // and when preferred width is ignored or ...
+            if (sizePolicy().horizontalPolicy()&QSizePolicy::IgnoreFlag
+                // or when preferred width is defined from outside
+                || !qFuzzyCompare(preferredWidth(), d->mAdjustedSize.width())) {
+                  // TODO: looking for better solution since preferredWidth() can cause call of sizeHint
+
+                // in those cases skip updateGeometry
+                return;
+            }
         }
-        if ( (sizePolicy().horizontalPolicy()&QSizePolicy::IgnoreFlag) && onlyHorizontalSizeHintChanged ) {
-            // suppress updateGeometry() and use the same geometry
-            d->setSize( size() );
-        } else {
-            updateGeometry();
-        }
-        update();
+        updateGeometry();
     }
 }
 
@@ -952,8 +1068,9 @@
 {
     Q_D(HbTextItem);
     if (elideMode != d->mElideMode) {
-        d->mInvalidateShownText = true;
         d->mElideMode = elideMode;
+        d->scheduleTextBuild();
+        prepareGeometryChange();
         update();
     }
 }
@@ -986,6 +1103,10 @@
         painter->drawRect(rect);
     }
 
+    if (d->mInvalidateShownText) {
+        d->rebuildTextLayout(size());
+    }
+
 
     painter->setPen(textColor());
 
@@ -1011,15 +1132,16 @@
  */
 void HbTextItem::setGeometry(const QRectF & rect)
 {
-    Q_D(HbTextItem);
-
     HbWidgetBase::setGeometry(rect);
 
-    // needed when there was no size change and some things
-    // need to relayout text
-    if(d->mInvalidateShownText) {
-        prepareGeometryChange();
-        d->setSize(rect.size());
+    if (parentLayoutItem() && parentLayoutItem()->isLayout()) {
+        // rect.size can't be used here since size can be limited inside of
+        // called method HbWidgetBase::setGeometry(rect) so size is used which
+        // holds current size
+        Q_D(HbTextItem);
+        if (d->isAdjustHightNeeded(size(), preferredSize())) {
+            updateGeometry();
+        }
     }
 }
 
@@ -1032,6 +1154,9 @@
 {
     Q_D(const HbTextItem);
 
+    if (d->mInvalidateShownText) {
+        const_cast<HbTextItemPrivate*>(d)->rebuildTextLayout(size());
+    }
     return d->boundingRect(contentsRect());
 } // boundingRect()
 
@@ -1044,6 +1169,21 @@
 
     QSizeF size(0,0);
 
+    // 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(20)
+                << " oldFont:" << d->mTextLayout.font()
+                << " newFont:" << font();
+#endif // HB_TEXT_ITEM_LOGS
+
+        const_cast<HbTextItemPrivate *>(d)->mTextLayout.setFont(font());
+        const_cast<HbTextItemPrivate *>(d)->clearAdjustedSizeCache();
+    }
+
     Qt::Orientations effectiveOrientations(0);
     if ( !(sizePolicy().horizontalPolicy()&QSizePolicy::IgnoreFlag) ) {
         effectiveOrientations |= Qt::Horizontal;
@@ -1058,71 +1198,32 @@
         return HbWidgetBase::sizeHint( which, constraint );
     }
 
-    const QFontMetricsF metrics(font());
-    QSizeF maxSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
-
-    if(constraint.width()>0) {
-        maxSize.setWidth(constraint.width());
-    }
-    if(constraint.height()>0) {
-        maxSize.setHeight(constraint.height());
-    }
-
     switch(which) {
     case Qt::MinimumSize: 
         {
             if ( !d->mText.isEmpty() ) {
-                size.setWidth( MinimumWidth ); // just to show something  -- should not matter in read use-case
-
-                if( d->mMinLines > 1 ) {
-                    size.setHeight( ( metrics.height() + metrics.leading() ) * d->mMinLines - metrics.leading() );
-                } else {
-                    size.setHeight( metrics.height() );
-                }
+                size.setWidth(MinimumWidth); // just to show something  -- should not matter in read use-case
+                size = d->respectSizeLimits(size);
             }
-
             break;
         }
 
     case Qt::PreferredSize: 
         {
-            if ( !(effectiveOrientations&Qt::Horizontal) && d->mMinLines > 0 && (d->mMinLines == d->mMaxLines) ) {
+            if ( !effectiveOrientations.testFlag(Qt::Horizontal)
+                    && (d->mMinLines == d->mMaxLines) ) {
                 //optimize single line if the horizontal sizeHint is ignored
-                size.setHeight( ( metrics.height() + metrics.leading() ) * d->mMinLines - metrics.leading() );
+                size = d->respectSizeLimits(size);
                 break;
             }
 
-            // do the heavy calculation
-            size = metrics.boundingRect(QRectF(QPointF(),maxSize),
-                d->textFlagsFromTextOption(),
-                d->mText).size();
-
-
-            if( ( constraint.width() < 0 ) && ( constraint.height() < 0 ) ) {
-
-                if( ( d->mNeedToAdjustSizeHint ) || ( d->oldSize != size ) ) {
-                    const_cast<HbTextItemPrivate*>(d)->adjustSizeHint();
-                }
-
-                qreal pref =  d->mPrefHeight;
-
-                if( d->mMaxLines > 0 ) {
-                    qreal maxLimit =  ( metrics.height() + metrics.leading() ) * d->mMaxLines - metrics.leading();
-                    if( maxLimit < pref ) {
-                        pref = maxLimit;
-                    }
-
-                }
-
-                const_cast<HbTextItemPrivate*>(d)->oldSize = size;
-                size.setHeight( pref );
-            }
-
+            size = d->calculatePrefferedSize(constraint);
+            size = d->respectSizeLimits(size);
             break;
         }
 
     default:
-        size = HbWidgetBase::sizeHint( which, constraint );
+        size = HbWidgetBase::sizeHint(which, constraint);
     }
 
     return size;
@@ -1140,16 +1241,30 @@
     switch(event->type()) {
     case QEvent::LayoutDirectionChange: {
             Q_D(HbTextItem);
-            d->mInvalidateShownText = true;
-            updateGeometry();
+            d->scheduleTextBuild();
         }
         break;
 
     case QEvent::FontChange: {
             Q_D(HbTextItem);
-            d->mInvalidateShownText = true;
-            prepareGeometryChange();
-            updateGeometry();
+
+            if (!d->mTextLayout.font().isCopyOf(font())) {
+
+#ifdef HB_TEXT_ITEM_LOGS
+                qDebug() << "fontChangeEvent: " << objectName()
+                        << " text: " << text().left(20)
+                        << " font: " << font();
+#endif // HB_TEXT_ITEM_LOGS
+
+                d->mTextLayout.setFont(font());
+                d->clearAdjustedSizeCache();
+                d->scheduleTextBuild();
+                prepareGeometryChange();
+                updateGeometry();
+            } else {
+                // ignoring event since it has no effect
+                return;
+            }
         }
         break;
 
@@ -1170,20 +1285,13 @@
 /*!
     \reimp
  */
-void HbTextItem::resizeEvent ( QGraphicsSceneResizeEvent * event )
+void HbTextItem::resizeEvent (QGraphicsSceneResizeEvent *event)
 {
     Q_D(HbTextItem);
 
     HbWidgetBase::resizeEvent(event);
 
-    d->setSize(event->newSize());
-
-    if( ( qAbs(event->oldSize().width() - event->newSize().width()) > EPSILON ) &&
-        ( ( event->oldSize().width() < preferredWidth() ) || ( event->newSize().width() < preferredWidth() ) ) ){
-        if( d->adjustSizeHint() ) {
-            updateGeometry();
-        }
-    }
+    d->scheduleTextBuild();
 }
 
 /*!
@@ -1205,9 +1313,23 @@
         textOption.setWrapMode(textWrapMode);
         d->mTextLayout.setTextOption(textOption);
         if(!d->mText.isEmpty()) {
-            d->mInvalidateShownText = true;
-            d->mNeedToAdjustSizeHint = true;
-            updateGeometry();
+            d->scheduleTextBuild();
+            prepareGeometryChange();
+            update();
+        }
+
+        // is size hint adjustable?
+        if (parentLayoutItem() && parentLayoutItem()->isLayout()) {
+            if (d->mAdjustedSize.isValid() &&
+                d->mAdjustedSize.width() > size().width()) {
+                // restore default size hint
+                d->mAdjustedSize = d->respectSizeLimits(
+                        QSizeF(d->mAdjustedSize.width(), d->mDefaultHeight));
+                d->mMinWidthForAdjust = d->mAdjustedSize.width();
+                d->mMaxWidthForAdjust = QWIDGETSIZE_MAX;
+
+                updateGeometry();
+            }
         }
     }
 }
@@ -1261,7 +1383,8 @@
 }
 
 /*!
-    Returns true if text is cliped when item geometry is to small.
+    Returns true if text is clipped when item geometry is too small.
+
     \sa HbTextItem::setTextClip(bool)
 
     Equvalent of QGraphicsItem::flags().testFlag(QGraphicsItem::ItemClipsToShape)
@@ -1287,14 +1410,17 @@
 void HbTextItem::setMinimumLines( int minLines )
 {
     Q_D( HbTextItem );
+    minLines = qMax(minLines, 1); // zero or nagative values are meanless and are restoring 1
+
 	d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMin, true);
 
     if( minLines != d->mMinLines ) {
         if( ( d->mMaxLines > 0 ) && ( minLines > d->mMaxLines ) ) {
             d->mMaxLines = minLines;
         }
+        d->mMinLines = minLines;
 
-        d->mMinLines = minLines;
+        // not needed?: d->clearAdjustedSizeCache(); // some condition?
         updateGeometry();
     }
 }
@@ -1317,12 +1443,18 @@
     Q_D( HbTextItem );
 	d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMax, true);
 
+    maxLines = qMax(maxLines, 0);
+
     if( maxLines != d->mMaxLines ) {
-        if( ( d->mMinLines > 0 ) && ( maxLines > 0 ) && ( maxLines < d->mMinLines ) ){
+        if ((maxLines > 0) && (maxLines < d->mMinLines)){
             d->mMinLines = maxLines;
         }
+        d->mMaxLines = maxLines;
 
-        d->mMaxLines = maxLines;
+        d->scheduleTextBuild();
+        prepareGeometryChange();
+        update();
+
         updateGeometry();
 #ifdef HB_TEXT_MEASUREMENT_UTILITY
         if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) {
@@ -1336,7 +1468,7 @@
     \sa HbTextItem::setMinimumLines()
     \sa HbTextItem::setMaximumLines()
     \sa HbTextItem::maximumLines()
-    \return "minimum lines" parameter
+    \return "minimum lines" parameter (zero value means unset)
  */
 int HbTextItem::minimumLines() const
 {