diff -r 000000000000 -r 16d8024aca5e src/hbcore/primitives/hbrichtextitem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hbcore/primitives/hbrichtextitem.cpp Mon Apr 19 14:02:13 2010 +0300 @@ -0,0 +1,533 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (developer.feedback@nokia.com) +** +** This file is part of the HbCore module of the UI Extensions for Mobile. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at developer.feedback@nokia.com. +** +****************************************************************************/ + +#include "hbrichtextitem.h" +#include "hbrichtextitem_p.h" +#include "hbtextutils_p.h" +#include "hbcolorscheme.h" +#include "hbevent.h" + +#include +#include +#include +#include +#include +#include +#include + +const int KMinimumLetersToShow = 4; + +static const QString KDefaultColorThemeName = "qtc_view_normal"; + +HbRichTextItemPrivate::HbRichTextItemPrivate() : + mAlignment(Qt::AlignLeft|Qt::AlignVCenter), + mTextOption(mAlignment), + mDontPrint(false), + mDontClip(false), + mRtf(0) +{ +} + +HbRichTextItemPrivate::~HbRichTextItemPrivate() +{ +} + +/* + * private constructor + */ +void HbRichTextItemPrivate::init() +{ + Q_Q(HbRichTextItem); + + q->setFlag(QGraphicsItem::ItemClipsToShape, !mDontClip); + q->setFlag(QGraphicsItem::ItemIsSelectable, false); + q->setFlag(QGraphicsItem::ItemIsFocusable, false); + + mRtf = new QTextDocument(q); + mRtf->setDocumentMargin(0.0); // no margins needed + + mTextOption.setWrapMode(QTextOption::NoWrap); + mRtf->setDefaultTextOption(mTextOption); + + mRtf->setDefaultFont(q->font()); +} + +void HbRichTextItemPrivate::clear() +{ + delete mRtf; +} + +int HbRichTextItemPrivate::textFlagsFromTextOption() const +{ + int flags = (int)mAlignment; + + switch(mTextOption.wrapMode()) { + case QTextOption::NoWrap: + flags |= Qt::TextSingleLine; + break; + case QTextOption::WordWrap: + flags |=Qt::TextWordWrap; + break; + case QTextOption::ManualWrap: + break; + case QTextOption::WrapAnywhere: + flags |=Qt::TextWrapAnywhere; + break; + case QTextOption::WrapAtWordBoundaryOrAnywhere: + flags |=Qt::TextWordWrap | Qt::TextWrapAnywhere; + break; + } + + if(mDontClip) flags |= Qt::TextDontClip; + if(mDontPrint) flags |= Qt::TextDontPrint; + + return flags; +} + +bool HbRichTextItemPrivate::setLayoutDirection(Qt::LayoutDirection newDirection) +{ + Qt::Alignment oldAlign = mTextOption.alignment(); + Qt::Alignment alignment = QStyle::visualAlignment(newDirection, mAlignment); + if(alignment!=oldAlign) { + mTextOption.setAlignment(alignment); + mRtf->setDefaultTextOption(mTextOption); + return true; + } + return false; +} + +void HbRichTextItemPrivate::setSize(const QSizeF &newSize) +{ + if(mRtf->size()!=newSize) { + Q_Q(HbRichTextItem); + mRtf->setTextWidth(newSize.width()); + calculateOffset(); + q->update(); + } +} + +// #define HB_RICH_TEXT_ITEM_ALWAS_SHOW_FIRST_LINE +void HbRichTextItemPrivate::calculateOffset() +{ + Q_Q(HbRichTextItem); + + qreal diff; + if(mAlignment.testFlag(Qt::AlignTop)) { + diff = 0.0; + } else { + diff = q->geometry().height() - mRtf->size().height(); + if(!mAlignment.testFlag(Qt::AlignBottom)) { + // default align Qt::AlignVCenter if no flags are set + diff*=0.5; + } + } +#ifdef HB_RICH_TEXT_ITEM_ALWAS_SHOW_FIRST_LINE + diff = qMax(diff, (qreal)0.0); +#endif + + if(diff!=mOffset.y()) { + mOffset.setY(diff); + q->prepareGeometryChange(); + } +} + +/*! + @proto + @hbcore + \class HbRichTextItem + \brief HbRichTextItem is a item for showing formatted text. + + + This is mainly used as a primitive in widgets. + It derives from HbWidgetBase so it can be layouted. + + */ + +/*! + Constructor for the class. + */ + +HbRichTextItem::HbRichTextItem(QGraphicsItem *parent) : + HbWidgetBase(*new HbRichTextItemPrivate, parent) +{ + Q_D(HbRichTextItem); + d->init(); +} + +/*! + Constructor which set content using \a html format. + */ +HbRichTextItem::HbRichTextItem(const QString &html, QGraphicsItem *parent) : + HbWidgetBase(*new HbRichTextItemPrivate, parent) +{ + Q_D(HbRichTextItem); + d->init(); + setText(html); +} + +/* + Constructor for internal use only + */ +HbRichTextItem::HbRichTextItem(HbRichTextItemPrivate &dd, QGraphicsItem *parent) : + HbWidgetBase(dd, parent) +{ + Q_D(HbRichTextItem); + d->init(); +} + +/*! + Destructor for the class. + */ +HbRichTextItem::~HbRichTextItem() +{ + Q_D(HbRichTextItem); + d->clear(); +} + +/*! + Sets the \a text in html format. + + \sa HbRichTextItem::text() + */ +void HbRichTextItem::setText(const QString &text) +{ + Q_D(HbRichTextItem); + if (d->mText != text) { + d->mText = text; + d->mRtf->setHtml(text); + updateGeometry(); + } +} + +/*! + Returns the text in html format. + + \sa HbRichTextItem::setText() + */ + +QString HbRichTextItem::text() const +{ + Q_D( const HbRichTextItem ); + return d->mText; +} + +/*! + Sets \a alignment for the text from Qt::Alignment enumeration. + + \sa HbRichTextItem::alignment() + */ +void HbRichTextItem::setAlignment(Qt::Alignment alignment) +{ + Q_D( HbRichTextItem ); + d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextAlign, true); + alignment &= Qt::AlignVertical_Mask | Qt::AlignHorizontal_Mask; + if( d->mAlignment!=alignment ) { + prepareGeometryChange(); + d->mAlignment = alignment; + d->calculateOffset(); + if(d->setLayoutDirection(layoutDirection())) { + update(); + } + } +} + +/*! + Returns alignment for the text from Qt::Alignment enumeration. + + \sa HbRichTextItem::setAlignment() + */ +Qt::Alignment HbRichTextItem::alignment() const +{ + Q_D( const HbRichTextItem ); + return d->mAlignment; +} + +/*! + \reimp + */ +void HbRichTextItem::paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + Q_D(HbRichTextItem); + + if(!d->mDontPrint) { + if(!d->mDontClip) { + painter->setClipRect(contentsRect(), Qt::IntersectClip); + } + painter->translate(d->mOffset); + QAbstractTextDocumentLayout::PaintContext context; + context.palette.setColor(QPalette::Text, textDefaultColor()); + d->mRtf->documentLayout()->draw(painter, context); + } +} + +/*! + \reimp + + Sets new position and relayouts text according to new size. + */ +void HbRichTextItem::setGeometry(const QRectF & rect) +{ + Q_D(HbRichTextItem); + + HbWidgetBase::setGeometry(rect); + + if(rect.isValid()) { + d->setSize(rect.size()); + } +} + +/*! + \reimp + */ +QRectF HbRichTextItem::boundingRect () const +{ + Q_D(const HbRichTextItem); + + QRectF result(d->mOffset, d->mRtf->size()); + + if(!d->mDontClip) { + // clip + result = result.intersect(QRectF(QPointF(), + size())); + } + return result; +} + +/*! + \reimp + Relayouts text according to new size. + */ +void HbRichTextItem::resizeEvent(QGraphicsSceneResizeEvent *event) +{ + Q_D(HbRichTextItem); + + d->setSize(event->newSize()); +} + +/*! + \reimp + This impelementation detects layout direction changes, font changes and theme changes. + */ +void HbRichTextItem::changeEvent(QEvent *event) +{ + Q_D(HbRichTextItem); + + switch(event->type()) { + case QEvent::LayoutDirectionChange: { + prepareGeometryChange(); + if(d->setLayoutDirection(layoutDirection())) { + update(); + } + } + break; + + case QEvent::FontChange: { + d->mRtf->setDefaultFont(font()); + updateGeometry(); + } + break; + + default: + // Listens theme changed event so that item size hint is + // update when physical font is changed. + if (event->type() == HbEvent::ThemeChanged) { + Q_D(HbRichTextItem); + d->mDefaultColor = QColor(); + if(!d->mColor.isValid()) { + update(); + } + } + } + HbWidgetBase::changeEvent(event); +} + +/*! + \reimp + For which = PreferredSize returns reasonable size (QTextDocument::adjustSize()). + For which = MinimumSize returns size of 4 first letters + \a constraint width is taken into account. + */ +QSizeF HbRichTextItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +{ + Q_D(const HbRichTextItem); + QSizeF result; + switch(which) { + case Qt::MinimumSize: { + QTextBlock textBlock = d->mRtf->begin(); + if(textBlock.isValid() && textBlock.layout()->lineCount() > 0) { + QTextLine line = textBlock.layout()->lineAt(0); + result.setHeight(line.height()); + int cursorPos(KMinimumLetersToShow); + result.setWidth( line.cursorToX(&cursorPos) ); + + qreal doubleDocMargin = d->mRtf->documentMargin() * (qreal)2.0; + result.rheight() += doubleDocMargin; + result.rwidth() += doubleDocMargin; + } else { + result = HbWidgetBase::sizeHint(which, constraint); + } + } + break; + + case Qt::PreferredSize: { + if(constraint.width()<=0) { + d->mRtf->adjustSize(); + } else { + d->mRtf->setTextWidth(constraint.width()); + } + result = d->mRtf->size(); + } + break; + + default: + result = HbWidgetBase::sizeHint(which, constraint); + } + return result; +} + +/*! + * @proto + * Sets the text wrapping mode. + * + * \sa HbRichTextItem::textWrapping + * \sa QTextOption::setWrapMode + */ +void HbRichTextItem::setTextWrapping(Hb::TextWrapping mode) +{ + Q_D(HbRichTextItem); + d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextWrapMode, true); + QTextOption::WrapMode textWrapMode = static_cast(mode); + + if(d->mTextOption.wrapMode()!=textWrapMode) { + prepareGeometryChange(); + d->mTextOption.setWrapMode(textWrapMode); + d->mRtf->setDefaultTextOption(d->mTextOption); + updateGeometry(); + } +} + +/*! + * @proto + * Returns style of text wrapping. + * + * \sa HbRichTextItem::setTextWrapping + * \sa QTextOption::wrapMode + */ +Hb::TextWrapping HbRichTextItem::textWrapping() const +{ + Q_D(const HbRichTextItem); + + return static_cast(d->mTextOption.wrapMode()); +} + +/*! + * Returns color used as a default text color. + * If invalid color was set color for text is fetch from parent widget. + * If invalid color was set and no parent widget was set this will return + * default foreground color. + * + * \sa setTextDefaultColor() + */ +QColor HbRichTextItem::textDefaultColor() const +{ + Q_D( const HbRichTextItem ); + + if (d->mColor.isValid()) { // Means user has set text color + return d->mColor; + } + if (!d->mDefaultColor.isValid()) { + d->mDefaultColor = HbColorScheme::color(KDefaultColorThemeName); + } + + return d->mDefaultColor; +} + +/*! + * Sets color of text. + * If invalid color was set color for text is fetch from parent widget. + * If invalid color was set and no parent widget was set default foreground color + * will be used + * + * \sa textDefaultColor() + */ +void HbRichTextItem::setTextDefaultColor(const QColor &color) +{ + Q_D(HbRichTextItem); + if (d->mColor != color) { + d->mColor = color; + update(); + } +} + +/*! + * Shows (default) or hides text. Size hint remains unchanged (same as when text is visible). + */ +void HbRichTextItem::setTextVisible(bool isVisible) +{ + Q_D(HbRichTextItem); + if( d->mDontPrint == isVisible ) { + d->mDontPrint = !isVisible; + update(); + } +} + +/*! + * Returns if text is visible. + */ +bool HbRichTextItem::isTextVisible() const +{ + Q_D(const HbRichTextItem); + return !d->mDontPrint; +} + +/*! + * Enables (default) or disables text clipping when item geometry is too small. + */ +void HbRichTextItem::setTextClip(bool cliping) +{ + Q_D(HbRichTextItem); + if( d->mDontClip == cliping ) { + prepareGeometryChange(); + d->mDontClip = !cliping; + setFlag(QGraphicsItem::ItemClipsToShape, cliping); + update(); + } +} + +/*! + * Returns true if text is clipped when item geometry is too small. + */ +bool HbRichTextItem::isTextClip() const +{ + Q_D(const HbRichTextItem); + return !d->mDontClip; +} + +// end of file