src/hbcore/primitives/hbtextitem.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbCore module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include "hbtextitem.h"
       
    27 #include "hbtextitem_p.h"
       
    28 #include "hbstyle.h"
       
    29 #include "hbtextutils_p.h"
       
    30 #include "hbcolorscheme.h"
       
    31 #include "hbevent.h"
       
    32 
       
    33 #include <QTextLayout>
       
    34 #include <QGraphicsSceneResizeEvent>
       
    35 #include <QPainter>
       
    36 #include <QTextOption>
       
    37 
       
    38 
       
    39 #ifdef HB_TEXT_MEASUREMENT_UTILITY
       
    40 #include "hbtextmeasurementutility_p.h"
       
    41 #include "hbfeaturemanager_p.h"
       
    42 #endif
       
    43 
       
    44 
       
    45 bool HbTextItemPrivate::outlinesEnabled = false;
       
    46 
       
    47 static const QString KDefaultColorThemeName = "qtc_view_normal";
       
    48 const int MinimumWidth = 5; // minimum width if there is some text.
       
    49 const int KLayoutCacheLimit = 64;
       
    50 
       
    51 HbTextItemPrivate::HbTextItemPrivate () :
       
    52     mAlignment(Qt::AlignLeft | Qt::AlignVCenter),
       
    53     mElideMode(Qt::ElideRight),
       
    54     mDontPrint(false),
       
    55     mDontClip(false),
       
    56     mTextDirection(Qt::LeftToRight),
       
    57     mInvalidateShownText(true),
       
    58     mOffsetPos(0,0),
       
    59     mPrefHeight(0),
       
    60     mMinLines(0),
       
    61     mMaxLines(0),
       
    62     mNeedToAdjustSizeHint(false),
       
    63     mUpdateColor(true)
       
    64 {
       
    65 }
       
    66 
       
    67 void HbTextItemPrivate::init(QGraphicsItem *)
       
    68 {
       
    69     Q_Q(HbTextItem);
       
    70 
       
    71     q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
       
    72     q->setFlag(QGraphicsItem::ItemClipsToShape, !mDontClip);
       
    73     q->setFlag(QGraphicsItem::ItemIsSelectable, false);
       
    74     q->setFlag(QGraphicsItem::ItemIsFocusable,  false);
       
    75 
       
    76     QTextOption textOption = mTextLayout.textOption();
       
    77     textOption.setWrapMode(QTextOption::WordWrap);
       
    78     mTextLayout.setTextOption(textOption);
       
    79     mTextLayout.setCacheEnabled(true);
       
    80 }
       
    81 
       
    82 void HbTextItemPrivate::clear()
       
    83 {
       
    84     // no implementation needed
       
    85 }
       
    86 
       
    87 bool HbTextItemPrivate::doLayout(const QString& text, const qreal lineWidth, qreal leading)
       
    88 {
       
    89     bool textTruncated = false;
       
    90     mInvalidateShownText = false;
       
    91 
       
    92     mTextLayout.setText(text);
       
    93     mTextLayout.setFont( q_func()->font() );
       
    94 
       
    95     qreal height = 0;
       
    96     mTextLayout.beginLayout();
       
    97     while (1) {
       
    98         QTextLine line = mTextLayout.createLine();
       
    99         if (!line.isValid())
       
   100             break;
       
   101 
       
   102         line.setLineWidth(lineWidth);
       
   103         height += leading;
       
   104         line.setPosition(QPointF(0, height));
       
   105         height += line.height();
       
   106         if( ( mMaxLines > 0 ) && ( mTextLayout.lineCount() >= mMaxLines ) ) {
       
   107             textTruncated = true;
       
   108             break;
       
   109         }
       
   110     }
       
   111     mTextLayout.endLayout();
       
   112 
       
   113     return textTruncated;
       
   114 }
       
   115 
       
   116 void HbTextItemPrivate::setSize(const QSizeF &newSize)
       
   117 {
       
   118     Q_Q(HbTextItem);
       
   119 
       
   120     updateTextOption();
       
   121 
       
   122     QFont usedFont = q->font();
       
   123     QFontMetricsF fontMetrics(usedFont);
       
   124 
       
   125     const qreal lineWidth = newSize.width();
       
   126 
       
   127     updateTextOption();
       
   128 
       
   129     QString tempText(mText);
       
   130     if(tempText.indexOf('\n')>=0) {
       
   131         // to prevent creation of deep copy if replace has no efect
       
   132         tempText.replace('\n', QChar::LineSeparator);
       
   133     }
       
   134 
       
   135     // function does the layout only when needed
       
   136     mTextLayout.setFont(usedFont);
       
   137 	// Need to call elidedText explicitly to enable multiple length translations.
       
   138     tempText = fontMetrics.elidedText(tempText, Qt::ElideNone, lineWidth);
       
   139     bool textTruncated = doLayout(tempText, lineWidth, fontMetrics.leading());
       
   140     if(mElideMode!=Qt::ElideNone && !tempText.isEmpty()) {
       
   141         if(mTextLayout.boundingRect().height()>newSize.height()
       
   142           || mTextLayout.boundingRect().width()>newSize.width() || textTruncated) {
       
   143             // TODO: Multiple length translations with multiline text
       
   144             doLayout(elideLayoutedText(newSize, fontMetrics),
       
   145                      lineWidth,
       
   146                      fontMetrics.leading());
       
   147         }
       
   148     }
       
   149     calculateVerticalOffset();
       
   150     q->update();
       
   151 }
       
   152 
       
   153 /*
       
   154     finds index of last line before given Y coordinate
       
   155     It is a binary search.
       
   156  */
       
   157 int HbTextItemPrivate::findIndexOfLastLineBeforeY(qreal y) const
       
   158 {
       
   159     int i=0,j=mTextLayout.lineCount();
       
   160 
       
   161     if( ( mMaxLines > 0 ) && ( mMaxLines < j ) ){
       
   162         j = mMaxLines;
       
   163     }
       
   164 
       
   165     while(i!=j) {
       
   166         int k = (i+j)>>1;
       
   167         if(mTextLayout.lineAt(k).naturalTextRect().bottom()>y) {
       
   168             j=k;
       
   169         } else {
       
   170             if(i==k) {
       
   171                 break;
       
   172             }
       
   173             i=k;
       
   174         }
       
   175     }
       
   176     return i;
       
   177 }
       
   178 
       
   179 QString HbTextItemPrivate::elideLayoutedText(const QSizeF& size, const QFontMetricsF& metrics) const
       
   180 {
       
   181     int lastVisibleLine =findIndexOfLastLineBeforeY(size.height());
       
   182     QTextLine lastLine = mTextLayout.lineAt(lastVisibleLine);
       
   183 
       
   184     // all visible lines without last visible line
       
   185     QString textToElide = mTextLayout.text();
       
   186     QString elidedText = textToElide.left(lastLine.textStart());
       
   187 
       
   188     if(!elidedText.isEmpty() && !elidedText.endsWith(QChar::LineSeparator)) {
       
   189         // needed to prevent to move "..." to line before last line
       
   190         elidedText.append(QChar::LineSeparator);
       
   191     }
       
   192 
       
   193     int n = lastLine.textLength();
       
   194     if(textToElide.at(lastLine.textStart()+n-1)!=QChar::LineSeparator) {
       
   195         n = -1;
       
   196     }
       
   197     elidedText.append(metrics.elidedText(textToElide.mid(lastLine.textStart(), n),
       
   198                                          mElideMode, size.width(),textFlagsFromTextOption()));
       
   199 
       
   200     return elidedText;
       
   201 }
       
   202 
       
   203 void HbTextItemPrivate::updateTextOption()
       
   204 {
       
   205     Q_Q(HbTextItem);
       
   206 
       
   207     QTextOption textOpt = mTextLayout.textOption();
       
   208     textOpt.setAlignment(QStyle::visualAlignment(q->layoutDirection(), q->alignment()));
       
   209     textOpt.setTextDirection (mTextDirection);
       
   210     mTextLayout.setTextOption(textOpt);
       
   211 }
       
   212 
       
   213 void HbTextItemPrivate::calculateVerticalOffset()
       
   214 {
       
   215     Q_Q(HbTextItem);
       
   216 
       
   217     mOffsetPos.setY(0);
       
   218     Qt::Alignment align = q->alignment();
       
   219     if(!align.testFlag(Qt::AlignTop) && (align & Qt::AlignVertical_Mask)!=0 ) {
       
   220         int index = mTextLayout.lineCount()-1;
       
   221         if(index>=0) {
       
   222             qreal diff = q->size().height();
       
   223             diff -= mTextLayout.lineAt(index).rect().bottom();
       
   224             if(align & Qt::AlignVCenter) {
       
   225                 diff *=(qreal)0.5;
       
   226             }
       
   227             if(diff>=0 || mElideMode==Qt::ElideNone) {
       
   228                 mOffsetPos.setY(diff);
       
   229             }
       
   230         }
       
   231     }
       
   232 }
       
   233 
       
   234 int HbTextItemPrivate::textFlagsFromTextOption() const
       
   235 {
       
   236     QTextOption textOtion = mTextLayout.textOption();
       
   237     int flags = (int)mAlignment;
       
   238 
       
   239     switch(textOtion.wrapMode()) {
       
   240     case QTextOption::NoWrap:
       
   241         flags |= Qt::TextSingleLine;
       
   242         break;
       
   243     case QTextOption::WordWrap:
       
   244         flags |= Qt::TextWordWrap;
       
   245         break;
       
   246     case QTextOption::ManualWrap:
       
   247         break;
       
   248     case QTextOption::WrapAnywhere:
       
   249         flags |= Qt::TextWrapAnywhere;
       
   250         break;
       
   251     case QTextOption::WrapAtWordBoundaryOrAnywhere:
       
   252         flags |= Qt::TextWordWrap | Qt::TextWrapAnywhere;
       
   253         break;
       
   254     }
       
   255 
       
   256     if(mDontClip)  flags |= Qt::TextDontClip;
       
   257     if(mDontPrint) flags |= Qt::TextDontPrint;
       
   258 
       
   259     return flags;
       
   260 }
       
   261 
       
   262 bool HbTextItemPrivate::adjustSizeHint()
       
   263 {
       
   264     Q_Q( HbTextItem );
       
   265 
       
   266     mNeedToAdjustSizeHint = false;
       
   267 
       
   268     if ( !(q->sizePolicy().verticalPolicy()&QSizePolicy::IgnoreFlag) ) {
       
   269         // only calculated if the vertical sizeHint is taken into account
       
   270 
       
   271         const QFontMetricsF metrics(q->font());
       
   272 
       
   273         if ( mMinLines > 0 && (mMinLines == mMaxLines) ) {
       
   274             // if the number of lines if fixed: optimize
       
   275             const qreal newPrefHeight = ( metrics.height() + metrics.leading() ) * mMinLines - metrics.leading();
       
   276             if( qAbs( mPrefHeight - newPrefHeight ) > 0.01 /* epsilon */ ) {
       
   277                 mPrefHeight = newPrefHeight;
       
   278                 return true;
       
   279             }
       
   280             return false;
       
   281         }
       
   282 
       
   283         QSizeF currSize = q->size();
       
   284         // do the heavy calculation
       
   285         QRectF desiredRect = metrics.boundingRect( QRectF( 0, 0 , currSize.width(), QWIDGETSIZE_MAX ), textFlagsFromTextOption(), mText );
       
   286 
       
   287         if( qAbs( desiredRect.height() - mPrefHeight ) > 0.01 /* epsilon */ ) {
       
   288             mPrefHeight = desiredRect.height();
       
   289             return true;
       
   290         }
       
   291     }
       
   292 
       
   293     return false;
       
   294 }
       
   295 
       
   296 
       
   297 /*!
       
   298     @alpha
       
   299     @hbcore
       
   300     \class HbTextItem
       
   301     \brief HbTextItem is a lightweight item for showing text.
       
   302 
       
   303 
       
   304     This is mainly used as a primitive in widgets.
       
   305     It derives from HbWidgetBase so it can be layouted.
       
   306  */
       
   307 
       
   308 /*!
       
   309     Constructor for the class with no content.
       
   310  */
       
   311 
       
   312 HbTextItem::HbTextItem (QGraphicsItem *parent) :
       
   313     HbWidgetBase(*new HbTextItemPrivate, parent)
       
   314 {
       
   315     Q_D(HbTextItem);
       
   316     d->init(parent);
       
   317 }
       
   318 
       
   319 
       
   320 /*!
       
   321     Constructs object with a \a text content.
       
   322  */
       
   323 HbTextItem::HbTextItem (const QString &text, QGraphicsItem *parent) :
       
   324     HbWidgetBase(*new HbTextItemPrivate, parent)
       
   325 {
       
   326     Q_D(HbTextItem);
       
   327     d->init(parent);
       
   328     setText(text);
       
   329 }
       
   330 
       
   331 /*
       
   332     Constructor for internal use only
       
   333  */
       
   334 HbTextItem::HbTextItem (HbTextItemPrivate &dd, QGraphicsItem * parent) :
       
   335     HbWidgetBase(dd, parent)
       
   336 {
       
   337     Q_D(HbTextItem);
       
   338     d->init(parent);
       
   339 }
       
   340 
       
   341 /*!
       
   342     Destructor for the class.
       
   343  */
       
   344 HbTextItem::~HbTextItem ()
       
   345 {
       
   346 }
       
   347 
       
   348 /*!
       
   349     Returns the text shown by object.
       
   350 
       
   351     \sa HbTextItem::setText()
       
   352  */
       
   353 QString HbTextItem::text () const
       
   354 {
       
   355     Q_D( const HbTextItem );
       
   356     return d->mText;
       
   357 }
       
   358 
       
   359 /*!
       
   360     Returns the text color used for paiting text.
       
   361     If no color was set it returns color based on theme.
       
   362 
       
   363     \sa HbTextItem::setTextColor()
       
   364  */
       
   365 QColor HbTextItem::textColor () const
       
   366 {
       
   367     Q_D( const HbTextItem );
       
   368 
       
   369     if (d->mColor.isValid()) { // Means user has set text color
       
   370         return d->mColor;
       
   371     }
       
   372     if (!d->mDefaultColor.isValid()) {
       
   373         d->mDefaultColor = HbColorScheme::color(KDefaultColorThemeName);
       
   374     }
       
   375     return d->mDefaultColor;
       
   376 }
       
   377 
       
   378 
       
   379 /*!
       
   380     Returns the text alignment. It suports vertical and horizontal alignment.
       
   381 
       
   382     \sa HbTextItem::setAlignment()
       
   383  */
       
   384 Qt::Alignment HbTextItem::alignment () const
       
   385 {
       
   386     Q_D( const HbTextItem );
       
   387     return d->mAlignment;
       
   388 }
       
   389 
       
   390 /*!
       
   391     Returns the elide mode of the text.
       
   392     This option decide how last line of text is truncated.
       
   393 
       
   394     \sa HbTextItem::setElideMode()
       
   395  */
       
   396 Qt::TextElideMode HbTextItem::elideMode () const
       
   397 {
       
   398     Q_D( const HbTextItem );
       
   399     return d->mElideMode;
       
   400 }
       
   401 
       
   402 /*!
       
   403     Sets the text into \a text.
       
   404  */
       
   405 void HbTextItem::setText (const QString &text)
       
   406 {
       
   407     Q_D(HbTextItem);
       
   408 
       
   409     QString txt( text );
       
   410 
       
   411 #ifdef HB_TEXT_MEASUREMENT_UTILITY
       
   412 
       
   413     if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) {
       
   414         if (text.endsWith(QChar(LOC_TEST_END))) {
       
   415             int index = text.indexOf(QChar(LOC_TEST_START));
       
   416             setProperty( HbTextMeasurementUtilityNameSpace::textIdPropertyName,  text.mid(index + 1, text.indexOf(QChar(LOC_TEST_END)) - index - 1) );
       
   417             setProperty( HbTextMeasurementUtilityNameSpace::textMaxLines, d->mMaxLines );
       
   418             txt = text.left(index);
       
   419         } else {
       
   420             setProperty( HbTextMeasurementUtilityNameSpace::textIdPropertyName,  QVariant::Invalid );
       
   421         }
       
   422     }
       
   423 #endif //HB_TEXT_MEASUREMENT_UTILITY
       
   424 
       
   425     if (d->mText != txt) {
       
   426         d->mInvalidateShownText = true;
       
   427         bool rightToLeft = HbTextUtils::ImplicitDirectionalityIsRightToLeft(
       
   428             txt.utf16(), txt.length(), 0 );
       
   429         d->mTextDirection = rightToLeft ? Qt::RightToLeft : Qt::LeftToRight;
       
   430         prepareGeometryChange();
       
   431         d->mText = txt;
       
   432         d->mTextLayout.setCacheEnabled(KLayoutCacheLimit >= d->mText.length());
       
   433         bool onlyHorizonalSizeHintChanged = false;
       
   434         if ( d->mMinLines > 0 && (d->mMinLines == d->mMaxLines) ) {
       
   435             onlyHorizonalSizeHintChanged = true;
       
   436         }
       
   437         if ( (sizePolicy().horizontalPolicy()&QSizePolicy::IgnoreFlag) && onlyHorizonalSizeHintChanged ) {
       
   438             // suppress updageGeometry() and use the same geometry
       
   439             d->setSize( size() );
       
   440         } else {
       
   441             updateGeometry();
       
   442         }
       
   443         update();
       
   444     }
       
   445 }
       
   446 
       
   447 /*!
       
   448     Sets the text color into \a color.
       
   449     If invalid color is used color from theme will be used.
       
   450 
       
   451     \sa HbTextItem::textColor()
       
   452  */
       
   453 void HbTextItem::setTextColor (const QColor &color)
       
   454 {
       
   455     Q_D(HbTextItem);
       
   456 	d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextColor, true);
       
   457     if (d->mColor != color) {
       
   458         d->mColor = color;
       
   459         update();
       
   460     }
       
   461 }
       
   462 
       
   463 /*!
       
   464     Sets the text alignment into \a alignment.
       
   465     It suports vertical and horizontal alignment.
       
   466 
       
   467     \sa HbTextItem::alignment()
       
   468  */
       
   469 void HbTextItem::setAlignment (Qt::Alignment alignment)
       
   470 {
       
   471     Q_D(HbTextItem);
       
   472 	d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextAlign, true);
       
   473     alignment &= Qt::AlignVertical_Mask | Qt::AlignHorizontal_Mask;
       
   474     if (d->mAlignment != alignment) {
       
   475         prepareGeometryChange();
       
   476         d->mAlignment = alignment;
       
   477         d->updateTextOption();
       
   478         d->calculateVerticalOffset();
       
   479 
       
   480         update();
       
   481     }
       
   482 }
       
   483 
       
   484 /*!
       
   485     Sets the elide mode into \a elideMode.
       
   486     The elide mode determines the truncation of the last line of text
       
   487     i.e. the "..." usage
       
   488 
       
   489     \sa HbTextItem::elideMode()
       
   490  */
       
   491 void HbTextItem::setElideMode (Qt::TextElideMode elideMode)
       
   492 {
       
   493     Q_D(HbTextItem);
       
   494     if (elideMode != d->mElideMode) {
       
   495         d->mInvalidateShownText = true;
       
   496         d->mElideMode = elideMode;
       
   497         update();
       
   498     }
       
   499 }
       
   500 
       
   501 /*!
       
   502     \reimp
       
   503 
       
   504     Paints text
       
   505  */
       
   506 void HbTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
       
   507 {
       
   508     Q_D(HbTextItem);
       
   509     Q_UNUSED(option);
       
   510     Q_UNUSED(widget);
       
   511 
       
   512      HbWidgetBase::paint(painter, option, widget);
       
   513 
       
   514     /* Reverted "text layouting optimization"
       
   515     if ( d->mInvalidateShownText ) {
       
   516         d->setSize( size() );
       
   517     }
       
   518     */
       
   519 
       
   520     if(!d->mDontPrint) {
       
   521         painter->setPen(textColor());
       
   522 
       
   523         d->mTextLayout.draw(painter,
       
   524                             d->mOffsetPos,
       
   525                             QVector<QTextLayout::FormatRange>(),
       
   526                             d->mDontClip?QRectF():contentsRect());
       
   527     }
       
   528 
       
   529     if (HbTextItemPrivate::outlinesEnabled){
       
   530         painter->setBrush(QBrush(QColor(255, 0, 0, 50)));
       
   531         QRectF rect(contentsRect());
       
   532         // to see border - bounding rect was cliping bottom and right border
       
   533         rect.adjust(0, 0, -1.0, -1.0);
       
   534         painter->drawRect(rect);
       
   535     }
       
   536 }
       
   537 
       
   538 /*!
       
   539     \reimp
       
   540 
       
   541     Sets geometry of text
       
   542  */
       
   543 void HbTextItem::setGeometry(const QRectF & rect)
       
   544 {
       
   545     /* Reverted "text layouting optimization" */
       
   546     Q_D(HbTextItem);
       
   547 
       
   548     HbWidgetBase::setGeometry(rect);
       
   549 
       
   550     // needed when tere was no size change and some things
       
   551     // need to relayout text
       
   552     if(d->mInvalidateShownText) {
       
   553         d->setSize(rect.size());
       
   554     }
       
   555 }
       
   556 
       
   557 /*!
       
   558     \reimp
       
   559 
       
   560     bounding rectangle.
       
   561  */
       
   562 QRectF HbTextItem::boundingRect () const
       
   563 {
       
   564     Q_D(const HbTextItem);
       
   565 
       
   566     QRectF result(d->mTextLayout.boundingRect());
       
   567     result.translate(d->mOffsetPos);
       
   568 
       
   569     if(!d->mDontClip) {
       
   570         // clip
       
   571         result = result.intersected(contentsRect());
       
   572     }
       
   573 
       
   574     if (HbTextItemPrivate::outlinesEnabled) {
       
   575         result = result.united(contentsRect());
       
   576     }
       
   577 
       
   578     return result;
       
   579 }
       
   580 
       
   581 /*!
       
   582     \reimp
       
   583  */
       
   584 QSizeF HbTextItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
       
   585 {
       
   586     Q_D(const HbTextItem);
       
   587 
       
   588     QSizeF size(0,0);
       
   589 
       
   590     Qt::Orientations effectiveOrientations(0);
       
   591     if ( !(sizePolicy().horizontalPolicy()&QSizePolicy::IgnoreFlag) ) {
       
   592         effectiveOrientations |= Qt::Horizontal;
       
   593     }
       
   594 
       
   595     if ( !(sizePolicy().verticalPolicy()&QSizePolicy::IgnoreFlag) ) {
       
   596         effectiveOrientations |= Qt::Vertical;
       
   597     }   
       
   598 
       
   599     if ( !effectiveOrientations ) {
       
   600         // if the whole sizeHint is ignored, return ASAP with default values (0<50<QMAX)
       
   601         return HbWidgetBase::sizeHint( which, constraint );
       
   602     }
       
   603 
       
   604     const QFontMetricsF metrics(font());
       
   605     QSizeF maxSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
       
   606 
       
   607     if(constraint.width()>0) {
       
   608         maxSize.setWidth(constraint.width());
       
   609     }
       
   610     if(constraint.height()>0) {
       
   611         maxSize.setHeight(constraint.height());
       
   612     }
       
   613 
       
   614     switch(which) {
       
   615     case Qt::MinimumSize: 
       
   616         {
       
   617             if ( !d->mText.isEmpty() ) {
       
   618                 size.setWidth( MinimumWidth ); // just to show something  -- should not matter in read use-case
       
   619 
       
   620                 if( d->mMinLines > 1 ) {
       
   621                     size.setHeight( ( metrics.height() + metrics.leading() ) * d->mMinLines - metrics.leading() );
       
   622                 } else {
       
   623                     size.setHeight( metrics.height() );
       
   624                 }
       
   625             }
       
   626 
       
   627             break;
       
   628         }
       
   629 
       
   630     case Qt::PreferredSize: 
       
   631         {
       
   632             if ( !(effectiveOrientations&Qt::Horizontal) && d->mMinLines > 0 && (d->mMinLines == d->mMaxLines) ) {
       
   633                 //optimize single line if the horizonal sizeHint is ignored
       
   634                 size.setHeight( ( metrics.height() + metrics.leading() ) * d->mMinLines - metrics.leading() );
       
   635                 break;
       
   636             }
       
   637 
       
   638             // do the heavy calculation
       
   639             size = metrics.boundingRect(QRectF(QPointF(),maxSize),
       
   640                 d->textFlagsFromTextOption(),
       
   641                 d->mText).size();
       
   642 
       
   643 
       
   644             if( ( constraint.width() < 0 ) && ( constraint.height() < 0 ) ) {
       
   645 
       
   646                 if( ( d->mNeedToAdjustSizeHint ) || ( d->oldSize != size ) ) {
       
   647                     const_cast<HbTextItemPrivate*>(d)->adjustSizeHint();
       
   648                 }
       
   649 
       
   650                 qreal pref =  d->mPrefHeight;
       
   651 
       
   652                 if( d->mMaxLines > 0 ) {
       
   653                     qreal maxLimit =  ( metrics.height() + metrics.leading() ) * d->mMaxLines - metrics.leading();
       
   654                     if( maxLimit < pref ) {
       
   655                         pref = maxLimit;
       
   656                     }
       
   657 
       
   658                 }
       
   659 
       
   660                 const_cast<HbTextItemPrivate*>(d)->oldSize = size;
       
   661                 size.setHeight( pref );
       
   662             }
       
   663 
       
   664             break;
       
   665         }
       
   666 
       
   667     default:
       
   668         size = HbWidgetBase::sizeHint( which, constraint );
       
   669     }
       
   670 
       
   671     return size;
       
   672 }
       
   673 
       
   674  /*!
       
   675     \reimp
       
   676 
       
   677     Detects: font changes, layout direction changes and theme changes.
       
   678  */
       
   679 void HbTextItem::changeEvent(QEvent *event)
       
   680 {
       
   681     // Listens theme changed event so that item size hint is
       
   682 
       
   683     switch(event->type()) {
       
   684     case QEvent::LayoutDirectionChange: {
       
   685             Q_D(HbTextItem);
       
   686             d->updateTextOption();
       
   687         }
       
   688         break;
       
   689 
       
   690     case QEvent::FontChange: {
       
   691             Q_D(HbTextItem);
       
   692             d->mInvalidateShownText = true;
       
   693             updateGeometry();
       
   694         }
       
   695         break;
       
   696 
       
   697     default:
       
   698         // comparing event->type() with dynamic values:
       
   699 
       
   700         if (event->type() == HbEvent::ThemeChanged) {
       
   701             Q_D(HbTextItem);
       
   702             d->mDefaultColor = QColor(); 
       
   703             if(!d->mColor.isValid()) {
       
   704                 update();
       
   705             }
       
   706         }
       
   707     }
       
   708     HbWidgetBase::changeEvent( event );
       
   709 }
       
   710 
       
   711 /*!
       
   712     \reimp
       
   713  */
       
   714 void HbTextItem::resizeEvent ( QGraphicsSceneResizeEvent * event )
       
   715 {
       
   716     Q_D(HbTextItem);
       
   717 
       
   718     HbWidgetBase::resizeEvent(event);
       
   719     /* Reverted "text layouting optimization"
       
   720     d->mInvalidateShownText = true;
       
   721     */
       
   722     d->setSize(event->newSize());
       
   723 
       
   724     if( ( qAbs(event->oldSize().width() - event->newSize().width()) > 0.01 ) &&
       
   725         ( ( event->oldSize().width() < preferredWidth() ) || ( event->newSize().width() < preferredWidth() ) ) ){
       
   726         if( d->adjustSizeHint() ) {
       
   727             updateGeometry();
       
   728         }
       
   729     }
       
   730 }
       
   731 
       
   732 /*!
       
   733     @proto
       
   734     Sets style of text wrapping. \a mode type will be changed to Hb::TextWraping
       
   735     after appropriate merge.
       
   736 
       
   737     \sa HbTextItem::textWrapping
       
   738     \sa QTextOption::setWrapMode
       
   739  */
       
   740 void HbTextItem::setTextWrapping(Hb::TextWrapping mode)
       
   741 {
       
   742     Q_D(HbTextItem);
       
   743 	d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextWrapMode, true);
       
   744     QTextOption::WrapMode textWrapMode = static_cast<QTextOption::WrapMode>(mode);
       
   745 
       
   746     QTextOption textOption = d->mTextLayout.textOption();
       
   747     if(textOption.wrapMode()!=textWrapMode) {
       
   748         textOption.setWrapMode(textWrapMode);
       
   749         d->mTextLayout.setTextOption(textOption);
       
   750         if(!d->mText.isEmpty()) {
       
   751             d->mInvalidateShownText = true;
       
   752             d->mNeedToAdjustSizeHint = true;
       
   753             updateGeometry();
       
   754         }
       
   755     }
       
   756 }
       
   757 
       
   758 /*!
       
   759     @proto
       
   760     returns style of text wrapping. Return value type will be changed to
       
   761     Hb::WrappMode after appropriate merge.
       
   762 
       
   763     \sa HbTextItem::setTextWrapping
       
   764     \sa QTextOption::wrapMode
       
   765  */
       
   766 Hb::TextWrapping HbTextItem::textWrapping() const
       
   767 {
       
   768     Q_D(const HbTextItem);
       
   769     return static_cast<Hb::TextWrapping>(d->mTextLayout.textOption().wrapMode());
       
   770 }
       
   771 
       
   772 /*!
       
   773     Shows (default) or hides text.
       
   774     Size hint remains unchanged (same as when text is visible).
       
   775 
       
   776     \sa HbTextItem::isVisible()
       
   777  */
       
   778 void HbTextItem::setTextVisible(bool isVisible)
       
   779 {
       
   780     Q_D(HbTextItem);
       
   781     if( d->mDontPrint == isVisible ) {
       
   782         d->mDontPrint = !isVisible;
       
   783         update();
       
   784     }
       
   785 }
       
   786 
       
   787 /*!
       
   788     Returns if text is visible.
       
   789 
       
   790     \sa HbTextItem::setTextVisible(bool)
       
   791  */
       
   792 bool HbTextItem::isTextVisible() const
       
   793 {
       
   794     Q_D(const HbTextItem);
       
   795     return !d->mDontPrint;
       
   796 }
       
   797 
       
   798 /*!
       
   799     enables (default) od disables text cliping when item geometry is to small.
       
   800 
       
   801     \sa HbTextItem::isTextClip()
       
   802  */
       
   803 void HbTextItem::setTextClip(bool cliping)
       
   804 {
       
   805     Q_D(HbTextItem);
       
   806     if( d->mDontClip == cliping ) {
       
   807         prepareGeometryChange();
       
   808         d->mDontClip = !cliping;
       
   809         setFlag(QGraphicsItem::ItemClipsToShape, cliping);
       
   810         update();
       
   811     }
       
   812 }
       
   813 
       
   814 /*!
       
   815     Returns true if text is cliped when item geometry is to small.
       
   816 
       
   817     \sa HbTextItem::setTextClip(bool)
       
   818  */
       
   819 bool HbTextItem::isTextClip() const
       
   820 {
       
   821     Q_D(const HbTextItem);
       
   822     return !d->mDontClip;
       
   823 }
       
   824 
       
   825 /*!
       
   826     Sets minimum number of lines for text item. If minimum number of lines is set,
       
   827     then text item will always draw at least this number of lines.
       
   828 
       
   829     If you set minimum lines bigger than maximum lines, then maximum lines parameter
       
   830     will be automatically increased.
       
   831 
       
   832     Pass negative or zero value as an input parameter to unset this constraint
       
   833 
       
   834     \sa HbTextItem::minimumLines()
       
   835     \sa HbTextItem::setMaximumLines()
       
   836     \sa HbTextItem::maximumLines()
       
   837  */
       
   838 void HbTextItem::setMinimumLines( int minLines )
       
   839 {
       
   840     Q_D( HbTextItem );
       
   841 	d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMin, true);
       
   842 
       
   843     if( minLines != d->mMinLines ) {
       
   844         if( ( d->mMaxLines > 0 ) && ( minLines > d->mMaxLines ) ) {
       
   845             d->mMaxLines = minLines;
       
   846         }
       
   847 
       
   848         d->mMinLines = minLines;
       
   849         updateGeometry();
       
   850     }
       
   851 }
       
   852 
       
   853 /*!
       
   854     Sets maximum number of lines for text item. If maximum number of lines is set,
       
   855     then text item will not draw more lines then this maximum.
       
   856 
       
   857     Pass negative or zero value as an input parameter to unset this constraint
       
   858 
       
   859     If you set maximum lines less than minimum lines, then minimum lines parameter
       
   860     will be automatically decreased.
       
   861 
       
   862     \sa HbTextItem::maximumLines()
       
   863     \sa HbTextItem::setMinimumLines()
       
   864     \sa HbTextItem::minimumLines()
       
   865  */
       
   866 void HbTextItem::setMaximumLines( int maxLines )
       
   867 {
       
   868     Q_D( HbTextItem );
       
   869 	d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextLinesMax, true);
       
   870 
       
   871     if( maxLines != d->mMaxLines ) {
       
   872         if( ( d->mMinLines > 0 ) && ( maxLines > 0 ) && ( maxLines < d->mMinLines ) ){
       
   873             d->mMinLines = maxLines;
       
   874         }
       
   875 
       
   876         d->mMaxLines = maxLines;
       
   877         updateGeometry();
       
   878 #ifdef HB_TEXT_MEASUREMENT_UTILITY
       
   879         if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) {
       
   880             setProperty( HbTextMeasurementUtilityNameSpace::textMaxLines, d->mMaxLines );
       
   881         }
       
   882 #endif
       
   883     }
       
   884 }
       
   885 
       
   886 /*!
       
   887     \sa HbTextItem::setMinimumLines()
       
   888     \sa HbTextItem::setMaximumLines()
       
   889     \sa HbTextItem::maximumLines()
       
   890     \return "minimum lines" parameter
       
   891  */
       
   892 int HbTextItem::minimumLines() const
       
   893 {
       
   894     Q_D( const HbTextItem );
       
   895     return d->mMinLines;
       
   896 }
       
   897 
       
   898 /*!
       
   899     \sa HbTextItem::setMaximumLines()
       
   900     \sa HbTextItem::setMinimumLines()
       
   901     \sa HbTextItem::minimumLines()
       
   902     \return "maximum lines" parameter
       
   903  */
       
   904 int HbTextItem::maximumLines() const
       
   905 {
       
   906     Q_D( const HbTextItem );
       
   907     return d->mMaxLines;
       
   908 }
       
   909 
       
   910 // end of file